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

Is there something like instance variables

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)

? lazy-initial-state;

  • ???: ????? 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()  }

????