React has two sets of apis: the Class API and the function-based hooks API. It is officially recommended to use hooks instead of classes. Because hooks are cleaner and require less code, they are “light” to use and classes are “heavy”. Also, hooks are functions, which are more in line with the React function nature.

Try to write components as pure functions. If you need external functions and side effects, use hooks to “hook” external code. React Hooks are those Hooks.

Class and function differences

  • A class is an encapsulation of data and logic. That is, the state and operation methods of a component are encapsulated together. If you choose a class, you should write all the relevant data and operations in the same class.

  • In general, a function should only do one thing, and that is return a value. If you have multiple operations, each operation should be written as a separate function. Furthermore, the state of the data should be separated from the method of operation. According to this philosophy, the React function component should only do one thing: return the component’s HTML code, and nothing else.

What are the side effects

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

This function does only one thing: it returns the HTML code of the component based on the input parameters. Functions that perform pure calculations (conversions) are called “pure functions” in functional programming, so where do you put operations that don’t involve computation (such as logging, storing data, changing application state, etc.)?

Functional programming refers to operations that have nothing to do with the calculation of data as “side effects.”

A hook is a hook

React hooks are the React function component’s solution for introducing side effects to function components.

The body of a function component should only be used to return the HTML code of the component; all other operations (side effects) must be introduced via hooks.

React provides special hooks for many common operations (side effects) :

  • useState(): Save state
  • useContext(): Save context
  • useRef(): Save reference
  • .

UseEffect () is a generic side effect hook. It can be used when no corresponding hook can be found.

Four, useEffect

import React, { useEffect } from 'react'; Function Welcome(props) {useEffect(() => {document.title = 'loading done '; }); return <h1>Hello, {props.name}</h1>; }Copy the code

In the example above, the argument to useEffect() is a function that is the desired side effect (changing the page title). React executes this function once the component is loaded.

1. UseEffect () is the second argument

function Welcome(props) {
  useEffect(() => {
    document.title = `Hello, ${props.name}`;
  }, [props.name]);
  return <h1>Hello, {props.name}</h1>;
}
Copy the code

The **componentDidUpdate()** method is used.

If the second argument is an empty array, then the side effect argument does not have any dependencies. Therefore, the side effects function is executed only once after the component is loaded into the DOM, and not again after the component is re-rendered. The **componentDidMount()** method.

2. Return value of useEffect()

Side effects occur as the component is loaded, and may need to be cleaned up when the component is unloaded.

UseEffect () allows you to return a function that is executed to clean up side effects when the component is unloaded.

useEffect(() => {
  const subscription = props.source.subscribe();
  return () => {
    subscription.unsubscribe();
  };
}, [props.source]);
Copy the code

In the example above, useEffect() subscribes to an event when the component is loaded and returns a cleanup function that unsubscribes when the component is unloaded. Function equivalent to **componentWillUnmount()** method.

3. Pay attention to the point

If there are multiple side effects, multiple useeffects () should be called rather than written together.

UseState () : state hook

const [state, setState] = React.useState(initialState);
Copy the code

Returns a state and a function to update the state.

The setState function is used to update state. It receives a new state value and queues a re-rendering of the component.

1. Functional updates

setState(i => i+1)
Copy the code

This form is preferred for multiple state operations

2. useStateUpdate objects are not merged automatically

We can use a functional setState in conjunction with the expansion operator to merge updated objects:

const [state, setState] = useState({}); SetState (prevState => {// Also use object. assign return {... prevState, ... updatedValues}; });Copy the code

3. Lazy initial state

The initialState parameter is only used in the initial rendering of the component and will be ignored in subsequent renderings. If the initial state needs to be computed through complex calculations, we can pass in a function that computes and returns the initial state, which is only called during the initial render:

const [state, setState] = useState(() => {
  const initialState = someExpensiveComputation(props);
  return initialState;
});
Copy the code

UseReducer () : Action hook

React itself does not provide state management, and external libraries are usually required. The most commonly used library for this is Redux.

The core concept of Redux is that components emit actions to communicate with the state manager. After the state manager receives the action, the Reducer function is used to calculate the newState. The Reducer function is in the form (state, action) => newState.

The useReducers() hook is used to introduce the Reducer function:

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

It is equivalent to a sophisticated version of useState. It receives a Reducer and returns the current state and its accompanying dispatch method.

UseReducer can be more useful than useState in some situations, such as when the state logic is complex and contains multiple subvalues, or when the next state depends on the previous state. Also, using useReducer can optimize performance for components that trigger deep updates because you can pass dispatches to child components instead of callbacks.

Here is an example of a counter. The Reducer function used to calculate the state is as follows:

const myReducer = (state, action) => {
  switch(action.type)  {
    case('countUp'):
      return  {
        ...state,
        count: state.count + 1
      }
    default:
      return  state;
  }
}
Copy the code

The component code is as follows:

function App() {
  const [state, dispatch] = useReducer(myReducer, { count:   0 });
  return  (
    <div className="App">
      <button onClick={() => dispatch({ type: 'countUp' })}>
        +1
      </button>
      <p>Count: {state.count}</p>
    </div>
  );
}
Copy the code

Because Hooks can provide shared state and Reducer functions, they can replace Redux in these areas, as follows:

  1. Put the data together in onestoreobject
  2. Focus all operations onreducer
  3. To create aContext
  4. Create read and write apis for data
  5. Put the contents of step 4 in step 3Context
  6. withContext.ProviderwillContextProvided to all components
  7. For each componentuseContextGet the read and write API

However, useReducer doesn’t provide middleware or time travel, so use Redux if you need them.

UseContext () : shared state hook

const value = useContext(MyContext);
Copy the code

Receives a context object (the return value of React. CreateContext) and returns the current value of the context. The current context value is determined by the < MyContext.provider > value prop of the upper-layer component closest to the current component.

If you need to share state between components, use useContext().

We now have two components, Navbar and Messages, and we want to share state between them:

<div className="App">
  <Navbar/>
  <Messages/>
</div>
Copy the code

The first step is to create a Context outside the component using the React Context API:

const AppContext = React.createContext({});
Copy the code

Component encapsulation code is as follows:

<AppContext.Provider value={{
  username: 'superawesome'
}}>
  <div className="App">
    <Navbar/>
    <Messages/>
  </div>
</AppContext.Provider>
Copy the code

In the code above, AppContext.Provider provides a Context object that can be shared by quilt components.

The code for the Navbar component is as follows:

const Navbar = () => {
  const { username } = useContext(AppContext);
  return (
    <div className="navbar">
      <p>AwesomeSite</p>
      <p>{username}</p>
    </div>
  );
}
Copy the code

Eight, useRef

const refContainer = useRef(initialValue);
Copy the code

UseRef returns a mutable ref object whose.current property is initialized as the passed parameter (initialValue). The ref object returned remains constant throughout the life of the component.

A common use case is to mandate access to child components:

function TextInputWithFocusButton() { const inputEl = useRef(null); Const onButtonClick = () => {// 'current' points to the text input element inputel.current.focus () mounted to the DOM; }; return ( <> <input ref={inputEl} type="text" /> <button onClick={onButtonClick}>Focus the input</button> </> ); }Copy the code

In essence, useRef is like a “box” that can hold a mutable value in its.current property.

Nine, useMemo

const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
Copy the code

Returns an memoized value.

Passing the “create” function and an array of dependencies as arguments to useMemo, it recalculates memoized values only when a dependency changes, equivalent to computed in Vue 2. This optimization helps avoid costly calculations every time you render.

Functions passed into useMemo are executed during rendering. Please do not perform non-rendering operations inside this function. Operations such as side effects are used by useEffect, not useMemo.

If the dependency array is not provided, useMemo evaluates the new value each time it renders.

** You can use useMemo as a means of performance optimization, but don’t use it as a semantic guarantee. ** In the future React may choose to “forget” some of the previous Memoized values and recalculate them at the next render, such as freeing memory for off-screen components. Write code that can run without useMemo first — then add useMemo to your code to optimize performance.

X. Custom Hook

A custom Hook is a function whose name begins with “**use**” that can call other hooks from within the function.

Unlike the React component, custom hooks do not need to have a special identity. We are free to decide what its arguments are and what it should return (if necessary). In other words, it’s just like a normal function. But its name should always start with use, so it can be seen at a glance that it meets Hook rules.

More content