React Hooks 深入系列 —— 设计模式
- 2019 年 10 月 3 日
- 筆記
??? React Hooks ??????????????? Hooks ?? class ?????, ?????? api ?????, ??? Hooks ???? class ????????????
React Logo ? Hooks
React ? logo ???????, ??????????????, React ?????????????; ? Hooks ????, ???? React ?????, ???? 4 ?????????????? —— Dan in React Conf(2018)
why Hooks?
?: ?????????
: ? Class ??? React ????? state ????????? function, ???????????????????????????, ??????????? HOC ? render props
????????????????????????
- ????, ????????, ?????????????, ???? bug ???; (hoc?render props)
- ??, ????????????????; (hoc?render props)
- ?????, ???????????? hoc, ????? hoc ?????????????; (hoc)
?: ??????????
: Class ?????? componentDidMount
?componentDidUpdate
?? componentWillUnMount
?????????????, ????????????????????????????, ???????????????
?: Class ???????: ? React ?? Class ????????, ?????? Class ? Constructor ? bind ?? this ???????; ??? class ? TypeScript ?????, ??? defaultValue ???????; ?? React Team ?? Class ????????????????
useState ???????????????
???????????????, ??????????????????
?????, ????????????
[name, setName] = useState('??') [age, setAge] = useState(12)
?????, ??????????
{value: name, setValue: setName} = useState('??') {value: name, setValue: setName} = useState(12)
Hooks ?????
Hooks ????????????????????? ?????????
const SomeContext = require('./SomeContext) function Example({ someProp }, hooks) { const contextValue = hooks.useContext(SomeContext) return <div>{someProp}{contextValue}</div> }
?????????????????(???? context ?????)
Hooks ? Class ??? setState ??????????
Hooks ?? setState ? Class ??????? Hooks ????? setState ????????????????, ???????:
setState(prevState => { return { ...prevState, ...updateValues } })
????? class ? Hooks ?? setState
??????????????, ?????? 4 ??? render ???????????:
????? React Hooks ?? Redux
? React 16.8 ????, ????????
?????, ???? React ??? useContext
?useReducer
????????? redux, ?? todoList ???????????:
import React, { createContext, useContext, useReducer } from "react" // ?? StoreContext const StoreContext = createContext() // ?? Provider ??? export const StoreProvider = ({reducer, initialState, children}) => { return ( <StoreContext.Provider value={useReducer(reducer, initialState)}> {children} </StoreContext.Provider> ) } // ??????? useStoreContext, ???? Provider ?? value export const useStoreContext = () => useContext(StoreContext)
?????????????????????, ?? context ???????????????? react-redux v7 ????????
Hooks ???????? props ?? state
React ????????????? usePrevious
? hooks ?????? props ?? state?
usePrevious
??????? ref ????????
function usePrevous(value) { const ref = useRef() useEffect(() => { ref.current = value }) return ref.current }
Hooks ???????????
? Hooks ??? useRef() ???? Class ??? this.something?
/* in a function */ const X = useRef() X.current // can read or write /* in a Class */ this.X // can read or write
Hooks ? getDerivedStateFromProps ?????
? React ???? ???? getDerivedStateFromProps
??????, ???????????????, Hooks ??? api, ?????? getDerivedStateFromProps ?????
function ScrollView({row}) { const [isScrollingDown, setISScrollingDown] = setState(false) const [prevRow, setPrevRow] = setState(null) // ??????? prevRow state ???????? row ???? if (row !== prevRow) { setISScrollingDown(prevRow !== null && row > prevRow) setPrevRow(row) } return `Scrolling down ${isScrollingDown}` }
Hooks ? forceUpdate ?????
???? useReducer
? hack forceUpdate
, ?????? forceUpdate ????
const [ignored, forceUpdate] = useReduce(x => x + 1, 0) function handleClick() { forceUpdate() }
Hooks ? shouldComponentUpdate ?????
? Hooks ????? useMemo
??? shouldComponentUpdate
?????, ? useMemo
?? props ??????
React.useMemo((props) => { // your component })
useMemo ? useCallback ???
useMemo(() => <component />) ??? useCallback(<component />)
- useCallback: ????????
- useMemo: ????????
????????????????
??????????????????????? demo
const { useState, useEffect } = React function Example({ someProp }) { function doSomething() { console.log(someProp) // ????? 1, ????? 2 ?????? } useEffect( () => { doSomething() }, [] // ? ??????, ??? doSomething ?????? someProps ?? ) return <div>example</div> } export default function() { const [value, setValue] = useState(1) return ( <> <Example someProp={value} /> <Button onClick={() => setValue(2)}>button</Button> </> ) }
?? demo ?, ?? button ??, ?????? 2?????????????
???: ????? useEffect
?, ???????????????????????????????, ???????????
function Example({ someProp }) { useEffect( () => { function doSomething() { console.log(someProp) } doSomething() }, [someProps] // ?????????? ) return <div>example</div> }
???: ??????????
function Example({ someProp }) { function doSomething() { console.log(someProp) } useEffect( () => { doSomething() }, [doSomething] ) return <div>example</div> }
????????????, ????? useCallback
????????????????????
function Example({ someProp }) { const doSomething = useCallback(() => { console.log(someProp) }, [someProp]) useEffect( doSomething(), [doSomething] ) return <div>example</div> }
?????????????
- ???: ??
useState
?????, ????
const [value, setValue] = useState(() => createExpensiveObj)
- ???: ????? useRef ??
function Image(props) { const ref = useRef(null) function getExpensiveObj() { if (ref.current === null) { ref.current = ExpensiveObj } return ref.current } // if need ExpensiveObj, call getExpensiveObj() }