React Hooks+Umi+TypeScript+Dva開發體驗

前端時間,接觸了hooks,研究了一段時間後感受使用起來十分方便,正好公司開了一個新的小項目,正好使用hooks來實踐一下。前端

技術選型

1.爲何選擇umi

在以前的文章中我也介紹過umi的優勢,在使用過umi後,感受本身的開發效率有很大的提高。umi的路由使用起來實在是讓我愛不釋手,詳細的我就不過多介紹了,有興趣的能夠去看我以前的文章react

2.爲何選擇TypeScript

TypeScript 是 Microsoft 開發和維護的一種面向對象的編程語言。它是 JavaScript 的超集,包含了 JavaScript 的全部元素,能夠載入 JavaScript 代碼運行,並擴展了 JavaScript 的語法。在使用TypeScript編程時,它能幫助你在寫代碼的過程當中考慮到各類類型上的問題,避免代碼運行時出現的意想不到的錯誤。使用了TypeScript能夠加強你代碼的健壯性,特別是大型項目的開發中,某些小小的改動都有可能對你的項目形成嚴重的後果。編程

3.爲何選擇Dva

其實使用React Hooks的目的就是爲了去redux,那我爲何還會使用基於redux-soga封裝的dva呢?緣由就在於hooks雖然很方便,但若是是一些很複雜的狀態須要去管理,這時候使用hooks就會有點兒費勁了。因此這時候結合dva來解決這種特別複雜的狀態管理是很方便的,原生的redux使用起來稍微有點兒麻煩,dva用起來很簡單,很爽,這就是我選擇dva的緣由。redux

4.爲何選擇React Hooks

這個是這篇文章的重點了,你在react開發過程當中有沒有碰見這三個問題。segmentfault

(一) 在組件組件複用狀態邏輯很難後端

React 沒有提供將可複用性行爲「附加」到組件的途徑(例如,把組件鏈接到 store)。若是你使用過 React 一段時間,你也許會熟悉一些解決此類問題的方案,好比 render props 和 高階組件。可是這類方案須要從新組織你的組件結構,這可能會很麻煩,使你的代碼難以理解。若是你在 React DevTools 中觀察過 React 應用,你會發現由 providers,consumers,高階組件,render props 等其餘抽象層組成的組件會造成「嵌套地獄」。儘管咱們能夠在 DevTools 過濾掉它們,但這說明了一個更深層次的問題:React 須要爲共享狀態邏輯提供更好的原生途徑。

(二) 複雜的組件變得難以理解數組

咱們常常維護一些組件,組件起初很簡單,可是逐漸會被狀態邏輯和反作用充斥。每一個生命週期經常包含一些不相關的邏輯。例如,組件經常在 componentDidMount 和 componentDidUpdate 中獲取數據。可是,同一個 componentDidMount 中可能也包含不少其它的邏輯,如設置事件監聽,而以後需在 componentWillUnmount 中清除。相互關聯且須要對照修改的代碼被進行了拆分,而徹底不相關的代碼卻在同一個方法中組合在一塊兒。如此很容易產生 bug,而且致使邏輯不一致。在多數狀況下,不可能將組件拆分爲更小的粒度,由於狀態邏輯無處不在。這也給測試帶來了必定挑戰。同時,這也是不少人將 React 與狀態管理庫結合使用的緣由之一。可是,這每每會引入了不少抽象概念,須要你在不一樣的文件之間來回切換,使得複用變得更加困難。

(三) 難以理解的class性能優化

除了代碼複用和代碼管理會遇到困難外,class 是學習 React 的一大屏障。你必須去理解 JavaScript 中 this 的工做方式,這與其餘語言存在巨大差別。還不能忘記綁定事件處理器。沒有穩定的語法提案,這些代碼很是冗餘。你們能夠很好地理解 props,state 和自頂向下的數據流,但對 class 卻束手無策。即使在有經驗的 React 開發者之間,對於函數組件與 class 組件的差別也存在分歧,甚至還要區分兩種組件的使用場景。

若是你也被這三種問題所困擾,這時候接觸hooks,你會發現打開了新世界的大門。從面向對象編程轉爲函數式編程,我感受釋放了本身,寫代碼變得又爽又飛快。antd

項目搭建

由於使用了umi,因此該項目也是用umi來搭建的,具體方法可查看以前文章。選擇ts版本,而後根據本身編程習慣,配置一下tslint規則就ok了。
這裏要注意一件重要的事情,升級react和react-dom的版本爲16.8.0以上,由於umi腳手架搭建的項目react版本爲16.7.0,而16.8.0是react正式支持hook的版本。dom

Hooks使用

1.useState

首先咱們來看一下官方的代碼。

import React, { useState } from 'react';

function Example() {
  // 聲明一個新的叫作 「count」 的 state 變量
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

使用起來十分簡單,函數式編程讓你不用再繼承Component,直接定義一個變量就行,能夠給這個變量看作你以前寫react中state的一個值。使用Hooks以後你不用再調用setState來更改state中的值,可使用你本身定義的更改方法,上面代碼中就是使用setCount來更改count的值,是否是很方便?

怎麼在hooks中使用TypeScript?

若是你使用Component來編寫你的組件,你須要經過interface來定義你state中值的類型,使用Hooks,你只須要這樣:

const [count, setCount] = useState<number>(0)

2.useEffect

Effect Hook 可讓你在函數組件中執行反作用操做,下面是官方代碼。

import React, { useState, useEffect } from 'react';

function Example() {
  const [count, setCount] = useState(0);

  // Similar to componentDidMount and componentDidUpdate:
  useEffect(() => {
    // Update the document title using the browser API
    document.title = `You clicked ${count} times`;
  });

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

這段代碼中使用了useEffect,可讓你在屏幕中顯示你點擊的次數。useEffect最大的好處我認爲就是去生命週期鉤子函數了,使用以後你不用再使用任何生命週期鉤子函數,這一點來看是否是就特別爽?useEffect爲何會實現去生命週期鉤子的做用呢?你能夠在函數中寫一個console.log,查看控制檯後你便會發現控制檯會一直打印你的console.log,因此useEffect會在組件的生命週期中一直被調用,咱們在使用的時候能夠告訴useEffect何時纔會被調用來進行性能優化。好比上面代碼咱們能夠這樣修改:

useEffect(() => {
    // Update the document title using the browser API
    document.title = `You clicked ${count} times`;
},[count])

這樣修改後useEffect會在count的值發生改變後才被調用。

怎麼清除在useEffect中調用的函數?

在開發過程當中咱們可能會使用到定時器,而異步隊列中的定時器在組件被銷燬後也會繼續執行,這樣便會形成內存泄漏,在Component中咱們會調用componentWillUnmount函數來清除定時器,在useEffect中咱們該怎麼辦呢?

import React, { useState, useEffect }  from 'react'
import moment from 'moment'
export default function () {
  const [nowTime, setNowTime] = useState(moment().format('YYYY年MM月DD日 ddd HH:mm'))

  useEffect(() => {
    const timer = setInterval(() => {
      setNowTime(moment().format('YYYY年MM月DD日 ddd HH:mm:ss'))
    }, 1000);
    return () => {
      clearInterval(timer);
    }
  },[nowTime])

  return (
    <>{nowTime}</>
  )
}

上面代碼就是一段很簡單的顯示當前時間的代碼,咱們能夠經過return函數在組件銷燬的時候清除useEffect中的定時器

使用Hooks來編寫一個表格組件

從後端獲取數據,而後在表格中渲染應該是很常見的一個功能了,下面咱們來看一下使用Hooks以後怎麼寫這種組件

import React, { useState, useEffect }  from 'react'
import { Table } from 'antd'
export default function () {
  const [tableData, setTableData] = useState<any[]>([])
  const [page, setPage] = useState<number>(1)
  const [pageSize, setPageSize] = useState<number>(15)
  const [count, setCount] = useState<number>(0)
  const [loading,setLoading] = useState<boolean>(true)

  useEffect(() => {
    fetch('www.baidu.com').then( function(data) {
        if(data) {
          setTableData(data.result)
          setCount(data.count)
          setLoading(false)
        }
    })
  },[page,pageSize])

  const onChangePage = (pageNumber: any) => setPage(pageNumber)

  const onChangePageSize = (value: number) => setPageSize(value)

  const columns = [
    {
      title: 'ID',
      dataIndex: 'id'
    },
    {
      title: '姓名',
      dataIndex: 'name'
    },
    {
      title: '電話',
      dataIndex: 'tel',
    },
    {
      title: '性別',
      dataIndex: 'gender',
    },
    {
      title: '年齡',
      dataIndex: 'age',
    },
  ]

  return (
    <>
      <Table
        bordered={false}
        rowKey={(r, i) => (i + '')}
        columns={columns}
        loading={loading}
        dataSource={tableData.length ? tableData : []}
        pagination={false}
        style={{ marginTop: 10 }}
        size="small"
      />
      <Row>
        <Col span={8}>
          <span>搜索到{props.count}條數據</span>
          <span style={{ margin: '0 20px' }}>共{Math.ceil(count / pageSize)}頁</span>
          <Select defaultValue={15} onChange={onChangePageSize}>
            <Option value={10}>10條/頁</Option>
            <Option value={15}>15條/頁</Option>
            <Option value={20}>20條/頁</Option>
            <Option value={30}>30條/頁</Option>
          </Select>
        </Col>
        <Col span={14} push={2} style={{display:'flex', justifyContent:'flex-end', marginRight: 10}}>
           <Pagination 
             showQuickJumper={true} 
             current={page} 
             pageSize={pageSize} 
             total={count} 
             onChange={onChangePage}
           />
        </Col>
      </Row>
    </>
  )
}

這樣就寫完一個功能完善的表格組件了,回想一下你以前是用Component面向對象編程時怎麼寫的,再看一下用Hooks函數式編程的代碼是否是簡單不少?趕忙來試試hooks吧,會讓你有寫代碼停不下來的感受。

相關文章
相關標籤/搜索