ts + hooks 的基本使用

背景

Hooks 是React 16.8中的新增功能。它們容許您在不編寫class的狀況下使用狀態和其餘React功能,關於原理性東西其餘大佬已經說不少了,我今天主要講實踐具體用法。javascript

關於recompose --- 高階組件 hoc 庫

做者本身寫很推崇 hookshtml

翻譯過來就是

基本api

官方連接傳送門
經常使用api:java

  • useState
  • useEffect
  • useReducer
  • useRef
  • useContext

經常使用 api

useState

const [storeCustomerBaseInfo, updateStoreCustomerBaseInfo] = useState({})
複製代碼

數組第一個值是你須要更新的值,第二個值是更新該值得函數 useState() 函數運行的時候給默認值 我這裏是給的空對象 具體更新栗子以下react

if (res.success) {
      const { storeCustomerBaseInfo, storeUserPayInfo } = res.data
      updateStoreCustomerBaseInfo(storeCustomerBaseInfo)
    }
複製代碼

useEffect

通俗點就是 componentDidMount,componentDidUpdate、componentWillUnmount三個生命週期的合集,
複製代碼

通常在這裏發起異步請求🌰git

useEffect(() => {
    getWebData(id)
  }, [id])
  const getWebData = async (id) => {
    const res = await CustomerService.getCustomerDeatil(id)
    if (res.success) {
      const { storeCustomerBaseInfo, storeUserPayInfo } = res.data
      updateStoreCustomerBaseInfo(storeCustomerBaseInfo)
    }
  }
複製代碼

細心的同窗會發現我在函數末尾多加了個參數 這裏至關於我相似於 didMount 方法,若是不加該參數,就會一直請求。 默認狀況下,它在第一次渲染以後和每次更新以後運行,你可能會發現更容易認爲效果發生在「渲染以後」,而不是考慮「掛載」和「更新」React保證DOM在運行‘效果’時已更新。 加參數就至關於自定義更新,好比我這裏加了 id 只有當id 從新變化的時候再執行該方法github

如何作一些取消操做呢?

好比定時器,發佈訂閱,有時候組件卸載的時候要取消這個時候該怎麼辦呢redux

解決辦法

return 一個新的函數api

useEffect(() => {
     fecth()
 return () => {
     clearTimeOut()
 }
})
複製代碼

useReducer

useState的替代方案。接受類型爲(state,action) => newState的reducer,並返回與dispatch方法配對的當前狀態。 (若是熟悉Redux,你已經知道它是如何工做的。) 用過 redux的相信對這個reducer 都不陌生 使用和redux 如出一撤數組

//actions.js
export const showMsg = 'SHOW_MSG'
export const openpoolInfo = 'OPENPOOL_INFO'
export const updateShowMsg = (data) => ({
type: showMsg,
data
})
export const updateOpenpoolInfo = (data) => ({
type: openpoolInfo,
data
})

複製代碼
  • reducer 部分
import {
showMsg,
openpoolInfo
} from './actions'
export const initState = {
showMsg: true,
openpoolInfo: {}
}
export const initReducer = (state, action) => {
switch (action.type) {
  case showMsg:
    return {
      ...state,
      showMsg: action.data
    }
  case openpoolInfo:
    return {
      ...state,
      openpoolInfo: action.data
    }
  default:
    return state
}
}

複製代碼

最後連接組件bash

import React, { useEffect, useReducer } from 'react'
import { Page } from '../../components'
import { Divider, Button, message } from 'antd'
import { CustomerService } from '../../service'
import BaseInfo from './base_info'
import Edit from './edit'
import { yuan2Fen, fen2Yuan } from '../../helper'
import { updateShowMsg, updateEditTotalOpenPoolAmount, updateOpenpoolInfo } from './store/actions'
import { initState, initReducer } from './store/reducer'
const OpenPool = (props) => {
  const [state, dispatch] = useReducer(initReducer, initState)
  const { params: {id} } = props.match
  useEffect(() => {
    getOpenpoolInfo(id)
  }, [id])
  const getOpenpoolInfo = async (id) => {
    const res = await CustomerService.getOpenpool(id)
    if (res.success) {
      dispatch(updateOpenpoolInfo(res.data))
    }
  }
  const editChange = (editTotalOpenPoolAmount) => {
    const { usedOpenPollAmount } = state.openpoolInfo
    const showMsg = fen2Yuan(usedOpenPollAmount) - editTotalOpenPoolAmount > 0
    dispatch(updateShowMsg(showMsg))
    dispatch(updateEditTotalOpenPoolAmount(editTotalOpenPoolAmount))
  }
  const getParms = () => {
    const { usedOpenPollAmount } = state.openpoolInfo
    return {
      customerId: id,
      usedOpenPollAmount,
      totalOpenPoolAmount: yuan2Fen(state.editTotalOpenPoolAmount)
    }
  }
  const updateAmount = async () => {
    const params = getParms()
    const res = await CustomerService.updateOpenpool(params)
    if (res.data) {
      message.success('操做成功')
    }
  }
  return (
    <Page title='xxx'>
      <BaseInfo {...state.openpoolInfo} />
      <Divider />
      <Edit
        showMsg={state.showMsg}
        {...state.openpoolInfo}
        editTotalOpenPoolAmount={state.editTotalOpenPoolAmount}
        editChange={editChange}
      />
    </Page>
  )
}
export default OpenPool

複製代碼

TS 的用法

其實和上面的沒太大變化只要設置類型就好了,固然你也能夠不設置

import { Button } from 'antd'
import * as React from "react";
const { useState } = React
const Home = () => {
 const [count, setCount] = useState(0)
 const [strings, setStrings] = useState<string[]>([])
 return (<div>
   <Button onClick={() => setCount(1)}>測試普通類型</Button>
   <Button onClick={() => setStrings([])}>測試檢測類型</Button>
 </div>)
}
export default Home

複製代碼

再來看看使用 interface

import { Button } from 'antd'
import * as React from "react";
const { useState } = React
interface IType {
 counts: number;
}

const About = () => {
 const [counts, setCount] = useState<IType[]>([]);
 return (<div> <Button onClick={() => setCount([{counts: 1}])}>測試普通類型</Button> <Button onClick={() => setCount([]}>測試普通類型</Button> </div>)
}
export default About

複製代碼
注意在某些 tslint 版本里面 定義interface 必定要用 Ixxx 開頭否則會一直爆紅 具體請看issue

彩蛋

以上是我我的的實踐,如今估計看完都會有疑問究竟是用 useState 仍是 useReducer, 看了國外某大神的文章你就明白了 傳送門

相關文章
相關標籤/搜索