This is the 10th day of my participation in the November Gwen Challenge. Check out the event details: The last Gwen Challenge 2021

useReducer

UseReducer is another way to keep the state of function components.

The way of useReducer is similar to that of Redux. Components are stored in a specific place. To change the state, actions are triggered by the Dispatch method provided by useReducer and received by reducer. The Reducer internally decides how to deal with the state according to the type of actions, and finally changes the state by returning values.

export default function DemoReducer() {
  function reducer(state, action) {
    switch (action.type) {
      case 'increment':
        return state + 1
      case 'decrement':
        return state - 1
      default:
        return state
    }
  }
  const [state, dispatch] = useReducer(reducer, 0)
  return (
    <div>
      <h1>{state}</h1>
      <button onClick={() => dispatch({ type: 'increment' })}>+1</button>
      <button onClick={() => dispatch({ type: 'decrement' })}>-1</button>
    </div>
  )
}
Copy the code

What are the advantages of useReducer over useState?

  1. When our child component wants to modify the data in the parent component, if the parent component uses the useReducer and the data to be modified is managed by the useReducer, we can directly pass the dispatch to the child component, so that the child component can modify the data in the parent component as long as the dispatch.
  2. For complex states with multiple subvalues, use useReducer to make it easy to change some of the data based on the type of action.

useContext

UseContext simplifies code for getting data across components when we use React. CreateContext.

import { createContext, useContext } from 'react' const Context = createContext() const Context2 = createContext() function Bar() { return ( <Context.Consumer> {value => ( <Context2.Consumer> {value2 => ( <h1> {value}++++++++++++++++{value2} </h1> )} </ context.consumer >)} function Bar2() {const value = useContext(Context) const value2 = useContext(Context2) return ( <h1> {value} ------ {value2} </h1> ) } function Foo() { // return <Bar></Bar> return <Bar2></Bar2> } export default function DemoContext() { return ( <Context.Provider value={100}> <Context2.Provider value={20}> <Foo></Foo> </Context2.Provider> </Context.Provider> ) }Copy the code

useRef

  • Gets the DOM element object
export default function DemoRef() {
  const ref = useRef()
  return (
    <div>
      <input ref={ref} onChange={() => console.log(ref.current.value)} />
    </div>
  )
}
Copy the code
  • Save data (across component lifecycle)

The saved data remains even if the component is re-rendered, and changes to the saved data do not trigger the component to re-render.

The data saved by useState is state data, which will trigger component re-rendering if the data is changed. The data saved by useRef is not state data, and changing the data will not trigger component re-rendering. We usually use useRef to save auxiliary data during the running process of the program.

export default function DemoRef() { const [count, setCount] = useState(0) // const timerId = null const timerId = useRef() useEffect(() => { timerId.current = setInterval(() => { setCount(count => count + 1) }, 1000) }, []) function stopInterval() { clearInterval(timerId.current) } return ( <div> <h1>{count}</h1> <button OnClick ={stopInterval}> Stop </button> </div>)}Copy the code

In the code above, if the timeId is not useRef, it will be reassigned every time the component is re-rendered, so we will not clear the timer when we clearInterval. But we used useRef, so the timerId is saved across the component lifecycle. So you can know the correct timer.

For example, you can also use useRef to keep the number of component renderings. If useRef is not available, you may need global variables.

Custom hooks (important)

  • Custom hooks are our own defined hook functions

  • Is a standard way to encapsulate and share logic

    • What logic is shared in one component and is needed by other components, so we can write this logic in a custom hook and call the custom hook from the component that needs this logic.
  • A custom hook is a function whose name begins with use

  • Custom hooks are a combination of logic and built-in hooks.

  • Custom hooks are much easier than renderProps and Hoc.

  • The purpose of custom hooks is to share logic between different components.