React Hooks?

First, you need to understand the react component

The React component is divided into the following types:

1. Functional Components (stateless components)

Functional (Stateless) Component, also called Stateless Component, is usually only responsible for rendering.

function Welcome(props) {
    return <h1>Hello, {props.name}</h1>; 
}
Copy the code

A Class Component is a Stateful Component, which is also called a container Component. There is interaction logic and business logic in general.

class Welcome extends React.Component {
  state = {
      name: 'tori,}componentDidMount(){the fetch (...). ; ... }render() {
  return (
      <>
          <h1>Hello, {this.state.name}</h1>
          <button onClick={()= >Enclosing setState ({name: "007"})} > change name</button>
      </>); }}Copy the code

Presentational Components, similar to functional (stateless) components.

const Hello = (props) = > {
  return (
    <div>
      <h1>Hello! {props.name}</h1>
    </div>)}Copy the code

conclusion

  • Function components must be stateless components, presentation components are generally stateless components;
  • A class component can be either stateful or stateless.
  • Container components are generally stateful components.
  • The principle of division is summarized as: divide and rule, high cohesion, low coupling
  • Most of the requirements can be met through a combination of the above components.

Before hooks, it was difficult to reuse state logic between components, solutions (HOC, Render Props) needed to reorganize component structures, and the code was difficult to understand. Observe React applications in React DevTools, and you’ll see that components made up of providers, consumers, high-order components, render props, and other abstraction layers form a nested hell. Component maintenance becomes more complex, such as event-listening logic that has to be bundled and unbundled in different life cycles, and complex pages (componentDidMount) that contain a lot of logic make code readable. The this in the class component is hard to understand, and the class does not compress well, and makes hot overloading unstable. See official introduction for more introduction. So hook comes to solve these problems:

  • Avoid hell nesting and improve readability.
  • Functional components that are easier to understand than classes.
  • The class component life cycle is too many and too complex, causing functional components to exist statically.
  • Address the shortcomings of HOC and Render Props.
  • UI and logic are easier to separate.

The official hooks API

1.useState

UseState is a basic API for react-hooks. It is used in several ways:

  1. UseState takes an initial value and returns an array of the current value and methods to modify it (like state and setState).
  2. UseState takes a function that returns an array.
  3. SetCount can accept a new value or a function that returns the new value.
1.  const [ count1, setCount1 ] = useState(0);
1.  const [ count2, setCount2 ] = useState(() = > 0);
1.  setCount1(1); / / modify state
Copy the code

Class this.setState update is state merge, setState is replacement in useState.

Although function components also have state, there are some differences between function state and class state:

  1. Function state is more granular, and class state is too mindless.
  2. Function state stores snapshots and class state stores the latest values.
  3. In the case of reference types, class state does not need to pass in a new reference, whereas function state must be guaranteed to be a new reference.

For point 2, take an example

In the first example, clicking ten times in a row increases the number on the page from 0 to 10. In the second example, click ten times in a row and the number on the page only grows from zero to one

The class component can refer to count through this.state, so every setTimeout will refer to the last count, so the count will be added as many times as it was clicked.

Each update in the Function Component re-executes the current function, which means that the count read in setTimeout is obtained through the closure. The count is actually the initial value, not the latest value since the last execution, so it is only incremented once.

2.useRef

To solve this problem, use useRef. UseRef is an object that has a current property, and no matter how many times the function component executes, useRef always returns the same object

UseRef has the following features:

  1. useRefIs a method that can only be used on function components.
  2. useRefIt’s a division stringref, functions,ref,createRefThe fourth kind of acquisitionrefMethods.
  3. useRefIt never changes during the rendering cycle, so it can be used to reference certain data.
  4. Modify theref.currentComponent rerendering is not caused.

3.useEffect

UseEffect is an Effect Hook, often used for some side effects operations, to a certain extent can act as componentDidMount, componentDidUpdate, componentWillUnmount these three life cycle. UseEffect is a very important method that is the soul of React Hooks. It is used in several ways:

  1. useEffectReceives two arguments, the callback function to execute and the dependent array.
  2. If the dependent array is an empty array, then the callback function is called after the first rendering (componentDidMount), returns a function that will be unloaded when the component (componentWillUnmount) is carried out.
  3. If you do not pass dependent arrays, then the callback function is called after each render (componentDidMount 和 componentDidUpdate) is carried out.
  4. If the dependency array is not an empty array, then the callback function (componentDidUpdate) is executed after each updated rendering of the dependency, which is usually either state or props.

UseEffect is important because it has the following functions:

  1. Replace parts of the life cycle, such as componentDidMount, componentDidUpdate, componentWillUnmount.
  2. More Reactive, like Mobx’s Reaction and Vue’s Watch.
  3. From imperative to declarative, you don’t need to focus on where you should do something, you just need to focus on the dependent data.
  4. UseEffect and use estate allow you to write a series of custom hooks.
useEffect vs useLayoutEffect

UseLayoutEffect is a Hook method with a similar name to useEffect. UseEffect is used 90% of the time, but in some cases you have to use useEffect. The difference between useEffect and useLayoutEffect is:

  1. UseEffect does not block browser rendering, whereas useLayoutEffect does.
  2. UseEffect is executed after the browser renders, useLayoutEffect is executed after the DOM update is complete and before the browser draws.

For example, if we use the useEffect method to update the position of the Demo, then during page rendering, we will see the original position of the Demo, and then the useEffect method will be executed. When we update the position of the Demo, we will see the position of the Demo changed on the page. But sometimes we don’t want the user to see the change process, it will be ugly, such as changing the position of an element, it will become flash past, this time need to use useLayoutEffect

4.useContext

Hook functions that share data across components

const value = useContext(MyContext); 
// MyContext is the context object (the return value of React. CreateContext)
// useContext returns the return value of MyContext.
// The current context value is determined by the < myContext. Provider> value prop of the upper-layer component closest to the current component.
Copy the code

UseContext components always re-render when the context value changes, so the more wrapped < myContext. Provider>, the deeper the hierarchy, the performance impact. When the value of < myContext. Provider> changes, all components are rerendered regardless of whether the component subscribed to content Value.

5.useReducer

const [state, dispatch] = useReducer(reducer, initialState);
Copy the code

Reducer is a pure function that can transform state from one process to another only through actions;

UseReducer is a process that passes (state,action) => newState, just like redux. Data flow: Dispatch (action) => Reducer Update state => Return the updated state

The official recommendation for the following scenarios requires useReducer better:

  • The state logic is complex and contains multiple child values, which can be processed centrally.
  • The next state depends on the previous state.
  • Want to build automated test cases more consistently.
  • Using useReducer can also optimize the performance of components that trigger deep updates if you want to change some of the state of child components at a deeper level, because you can pass dispatches to child components instead of callbacks.

Using reducer helps separate reads from writes.

6.useMemo

UseMemo is similar to useEffect and is often used to cache the results of complex calculations. UseMemo receives a function and an array of dependencies. When the dependencies in the array change, the function is executed, returning the new value.

const sum = useMemo(() = > {
    // a series of calculations
}, [count])
const memoizedValue = useMemo(() = >computeExpensiveValue(a, b), [a, b]);; Returns a Memoized value. As with useCallback, the memoized value is recalculated when the dependency changes. UseMemo differs from useCallback in that it allows you to apply Memoized to any value type (not just functions).Copy the code

Each time the DatePicker component opens or switches months, it requires a lot of calculation to figure out which dates are currently displayed. The result is then rendered into a cell, which can be cached using useMemo and only computed when the date passed in changes.

  • UseMemo is executed before Render
  • If the dependency array is not provided, useMemo evaluates the new value each time it renders.
  • UseMemo is used to return memoize to prevent the overhead of large computations per render.
  • Be careful with useMemo optimization, because optimization itself brings computation, and most of the time, you don’t need to worry about optimizing unnecessary re-renders

7.useCallback

Similar to useMemo, except useCallback is used to cache functions.

const memoizedCallback = useCallback( () = > { doSomething(a, b); }, [a, b], );
// Returns an memoized callback function.
Copy the code

Summary: useCallback will return a callback version of the memory, changed only if one of the dependencies has changed. This approach is useful when passing callbacks to optimized subcomponents that depend on reference equality to prevent unnecessary rendering. Using the callback function passed as an argument, the render function changes each time, also causing the child component rerender, which useCallback can optimize.