First, the react API

var React = {
  Children: {
    map: mapChildren,
    forEach: forEachChildren,
    count: countChildren,
    toArray: toArray,
    only: onlyChild
  },
  createRef: createRef,
  Component: Component,
  PureComponent: PureComponent,
  createContext: createContext,
  forwardRef: forwardRef,
  lazy: lazy,
  memo: memo,
  useCallback: useCallback,
  useContext: useContext,
  useEffect: useEffect,
  useImperativeHandle: useImperativeHandle,
  useDebugValue: useDebugValue,
  useLayoutEffect: useLayoutEffect,
  useMemo: useMemo,
  useReducer: useReducer,
  useRef: useRef,
  useState: useState,
  Fragment: REACT_FRAGMENT_TYPE,
  Profiler: REACT_PROFILER_TYPE,
  StrictMode: REACT_STRICT_MODE_TYPE,
  Suspense: REACT_SUSPENSE_TYPE,
  createElement: createElementWithValidation,
  cloneElement: cloneElementWithValidation,
  createFactory: createFactoryWithValidation,
  isValidElement: isValidElement,
  version: ReactVersion,
  __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED: ReactSharedInternals
};
Copy the code
1, the children

There are a bunch of methods for handling props. Children, because children is an arraylike data structure but not an array, and you can use the React. children plugin if you want to handle it

2.createRef

React will discard the string ref usage of

. In the future, you can only use ref in two ways

class App extends React.Component{
  constructor() {
    this.ref = React.createRef()
  }
  render() {
    return <div ref={this.ref} />
    // or
    return <div ref={(node) => this.funRef = node} />
  }
}
Copy the code
3.component && PureComponent

The two classes are essentially the same, except that the PureComponent prototype has an extra identity

if (ctor.prototype && ctor.prototype.isPureReactComponent) { return ( ! shallowEqual(oldProps, newProps) || ! shallowEqual(oldState, newState) ); }Copy the code

This is a check to see if the Component needs to be updated. Ctor is the class you declare that inherits from Component or PureComponent. Ctor determines whether you inherit from Component or PureComponent, and if so, shallowEqual compares state and props.

By the way: There are only two places in React to compare whether a ClassComponent needs to update. ShouldComponentUpdate (); shouldComponentUpdate (); shouldComponentUpdate ()

4.createContext

CreateContext is the official context solution. We used the old context API which was not recommended by React. The new API will be released in version 17.

const { Provider, Consumer } = React.createContext('defaultValue')
const ProviderComp = (props) => (
  <Provider value={'realValue'}>
    {props.children}
  </Provider>
)
const ConsumerComp = () => (
  <Consumer>
    {(value) => <p>{value}</p>}
  </Consumber>
)
Copy the code
5.forwardRef

The forwardRef is used to solve the problem of HOC components transferring refs. HOC is a Higher Order Component. For example, when using redux, connect is used to bind the required state to the Component. This is essentially wrapping our component around a layer of components, and then passing it through… Passes external props to the actual component. The forwardRef can be used as follows:

const TargetComponent = React.forwardRef((props, ref) => (
  <TargetComponent ref={ref} />
))
Copy the code

This is why createRef is provided as the new ref method, which cannot be passed as a parameter if you use string ref.

6.lazy

Lazy functions allow you to handle dynamically imported usage just like regular components:

const OtherComponent = React.lazy(() => import('./OtherComponent'));
Copy the code
7.memo

React.memo(…) React V16.6 is a new feature. It is similar to the React.PureComponent in that it helps control the re-rendering of function components. React.memo(…) The react. PureComponent corresponds to the class component

onst Funcomponent = ()=> {
    return (
        <div>
            Hiya!! I am a Funtional component
        </div>
    )
}
const MemodFuncComponent = React.memo(Funcomponent)
Copy the code

React. Memo will return a pure MemodFuncComponent. We will render this component in a JSX tag. Whenever the props and state in the component change, React checks that the previous state and props and the next props and state are equal. If they are not equal, the function component will be rerendered. If they are equal, the function component will not be rerendered.

8.useCallback

Passing the inline callback function and the array of dependencies as arguments to useCallback returns the Memoized version of the callback function, which is updated only when a dependency changes. This is useful when you pass callback data to child components that are optimized and use reference equality to avoid unnecessary rendering (such as shouldComponentUpdate).

UseCallback (fn, deps) is equivalent to useMemo(() => FN, deps).

const memoizedCallback = useCallback(
  () => {
    doSomething(a, b);
  },
  [a, b],
);
Copy the code
9.useContext

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. When the most recent <MyContext.Provider> update is made to the component’s upper layer, the Hook triggers a rerender and uses the latest context value passed to MyContext Provider. Even if the ancestor uses React. Memo or shouldComponentUpdate, it will be rerendered when the component itself uses useContext. The argument to useContext must be the context object itself

const value = useContext(MyContext);
Copy the code

Components that call useContext are always rerendered when the context value changes. If rerendering components is expensive, you can optimize them by using Memoization.

10.useEffect

Effect Hook allows you to perform side effects in function components

import React, { useState, useEffect } from 'react'; function Example() { const [count, setCount] = useState(0); // componentDidMount and componentDidUpdate: useEffect(() => {document.title = 'You clicked ${count} times'; }); return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}> Click me </button> </div> ); }Copy the code

UseEffect Hook can be regarded as a combination of componentDidMount, componentDidUpdate and componentWillUnmount. What does the useEffect do? By using this Hook, you can tell the React component that it needs to do something after rendering. React saves the function you passed (we’ll call it “effect”) and calls it after a DOM update. In this effect, we set the Document title property, but we can also perform data fetching or call other imperative apis.

Why is useEffect called inside a component? Putting useEffect inside the component allows us to access the count State variable (or other props) directly in effect. We don’t need a special API to read it — it’s already saved in function scope. Hook uses JavaScript’s closure mechanism rather than introducing a specific React API when JavaScript already provides a solution.

Will useEffect be executed after every render? Yes, by default, it is executed after the first render and after every update. (We’ll talk about how to control it later.) You might be more comfortable with the idea that an effect happens “after rendering,” without having to worry about “mount” or “update.” React ensures that the DOM is updated every time an Effect is run.

UseEffect Deletes data
import React, { useState, useEffect } from 'react'; function FriendStatus(props) { const [isOnline, setIsOnline] = useState(null); useEffect(() => { function handleStatusChange(status) { setIsOnline(status.isOnline); } ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange); // Specify how to clean up after this effect: return function cleanup() { ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange); }; }); if (isOnline === null) { return 'Loading... '; } return isOnline ? 'Online' : 'Offline'; }Copy the code

Why return a function in effect? This is the optional clearing mechanism for Effect. Each effect can return a cleanup function. This puts the logic for adding and removing subscriptions together. They are all part of Effect.

React when to remove an effect? React performs cleanup operations when components are uninstalled. As you learned earlier, an effect is executed every time it is rendered. This is why React cleans up the previous effect before executing the current effect. We’ll talk later about why this helps avoid bugs and how to skip this behavior when you encounter performance problems.

11, useImperativeHandle

UseImperativeHandle allows you to customize the instance value exposed to the parent component when using a ref. In most cases, imperative code like ref should be avoided. UseImperativeHandle should be used with the forwardRef:

function FancyInput(props, ref) {
  const inputRef = useRef();
  useImperativeHandle(ref, () => ({
    focus: () => {
      inputRef.current.focus();
    }
  }));
  return <input ref={inputRef} ... />;
}
FancyInput = forwardRef(FancyInput);
Copy the code

In this case, the rendered parent component can call inputref.current. Focus ().

12, useDebugValue

UseDebugValue can be used to display tags for custom hooks in the React developer tool. For example, a custom Hook named useFriendStatus described in the “Custom Hook” section:

function useFriendStatus(friendID) { const [isOnline, setIsOnline] = useState(null); / /... "FriendStatus: Online" useDebugValue(isOnline? 'Online' : 'Offline'); return isOnline; }Copy the code
Delay formatting debug values

In some cases, formatting the display of values can be an expensive operation. There is no need to do this unless you need to check the Hook. Therefore, useDebugValue accepts a formatting function as an optional second argument. This function is called only when the Hook is checked. It takes a debug value as an argument and returns a formatted display value. For example, a custom Hook that returns a Date value can avoid unnecessary toDateString calls by formatting functions:

useDebugValue(date, date => date.toDateString());
Copy the code
14, useLayoutEffect

The function signature is the same as useEffect, but it calls Effect synchronously after all DOM changes. You can use it to read DOM layouts and trigger rerenders synchronously. The update schedule inside useLayoutEffect is refreshed synchronously before the browser performs the drawing.

Use standard Useeffects whenever possible to avoid blocking visual updates

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

You pass in the create function and the dependency array as arguments to useMemo, which recalculates memoized values only when a dependency changes. This optimization helps avoid costly calculations every time you render.

Remember that 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 might choose to “forget” some of the previous Memoized values and recalculate them at the next rendering, 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.

16, useReducer
const [state, dispatch] = useReducer(reducer, initialArg, init);
Copy the code

An alternative to useState. It receives a Reducer of the form (state, action) => newState and returns the current state and its accompanying dispatch method. (If you’re familiar with Redux, you already know how it works.)

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.

const initialState = {count: 0};
function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return {count: state.count + 1};
    case 'decrement':
      return {count: state.count - 1};
    default:
      throw new Error();
  }
}
function Counter() {
  const [state, dispatch] = useReducer(reducer, initialState);
  return (
    <>
      Count: {state.count}
      <button onClick={() => dispatch({type: 'decrement'})}>-</button>
      <button onClick={() => dispatch({type: 'increment'})}>+</button>
    </>
  );
}
Copy the code
17, 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.

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.

You should be familiar with ref, the main way to access the DOM. If you set the ref object to

React sets the.current property of the ref object to the corresponding DOM node, regardless of how the node changes.

However, useRef() is more useful than the ref attribute. It makes it easy to store any mutable value, similar to the way instance fields are used in class.

This is because it creates a normal Javascript object. UseRef () and create a {current:… The only difference with the} object is that useRef returns the same ref object every time it renders.

Remember that useRef does not notify you when the ref object contents change. Changing the.current property does not cause component rerendering. If you want to run some code when React binds or unbinds the REF of the DOM node, you need to use the ref callback to do so

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

Returns a state and a function to update the state. During initial rendering, the state returned is the same as the value of the first parameter passed in. The setState function is used to update state. It receives a new state value and queues a re-rendering of the component. In subsequent rerenders, the first value returned by useState will always be the latest state after the update. If the new state needs to be computed using the previous state, you can pass the function to setState. This function takes the previous state and returns an updated value. The following Counter component example shows two uses of setState: function Counter({initialCount}) {const [count, setCount] = useState(initialCount); return ( <> Count: {count}

19, type,
Fragment: REACT_FRAGMENT_TYPE,
StrictMode: REACT_STRICT_MODE_TYPE,
unstable_AsyncMode: REACT_ASYNC_MODE_TYPE,
unstable_Profiler: REACT_PROFILER_TYPE,
Copy the code

These four components are provided by React, but they are just placeholders and symbols. React will do some special processing when it actually detects them. StrictMode and AsyncMode, for example, will make all the Fiber modes of their child nodes the same mode as theirs

CreateElement & cloneElement & createFactory & isValidElement

CreateElement is the most important API for creating ReactElement in React. However, many people have never seen or used this API before. Because you are using JSX, JSX is not a standard JS, so it has to be compiled to make it a runnable JS, and when compiled, createElement appears:

// jsx <div id="app">content</div> // js React.createElement('div', { id: 'app'}, 'content') cloneElement is used to clone a ReactElement and createFactory is used to create a factory for creating a particular type of ReactElement.  export function createFactory(type) { const factory = createElement.bind(null, type); factory.type = type; return factory; }Copy the code

This is createElement with the first parameter attached to it. JSX does not use this API when programming. IsValidElement is a ReactElement