Read the source code of React-8

Keywords: Front-end React

Read the source code of React-8

ReactHooks

Hook yes React 16.8 New features for. It allows you to write class Use in case of state And others React Characteristic.

import {
  useCallback,
  useContext,
  useEffect,
  useImperativeHandle,
  useDebugValue,
  useLayoutEffect,
  useMemo,
  useReducer,
  useRef,
  useState,
  useResponder,
} from './ReactHooks';

useState

useState returns a pair of values: the current state and a function that lets you update it, which you can call in the event handler or elsewhere

It is similar to this.setState of the class component, but it will not merge the new state with the old state;

import React, { useState } from "react";
import "./App.css";

function App() {
  const [count, setCount] = useState(0);
  return (
    <div className="App">
      <div>
        <p>You clicked {count} times</p>
        <button onClick={() => setCount(count + 1)}>Click me</button>
      </div>
    </div>
  );
}

export default App;

useEffect

import React, { useState, useEffect } from "react";
import "./App.css";

function App() {
  const [count, setCount] = useState(0);
  useEffect(() => {
    // Update the document title using the browser API
    document.title = `You clicked ${count} times`;
  });
  return (
    <div className="App">
      <div>
        <p>You clicked {count} times</p>
        <button onClick={() => setCount(count + 1)}>Click me</button>
      </div>
    </div>
  );
}

export default App;

Equivalent to the life cycle function of React class, you can think of useEffect Hook as a combination of three functions: componentDidMount, componentDidUpdate and componentWillUnmount.

By default, effect is executed after each round of component rendering. In this case, once
If the dependency of effect changes, it will be recreated.

A second parameter can be passed to useEffect, which is an array of values on which effect depends. The updated example is as follows:

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

If you want to execute an effect that runs only once (only when the component is mounted and unloaded), you can pass an empty array ([]) as the second parameter. This tells React that your effect does not depend on any value in props or state, so it never needs to be repeated. This is not a special case - it still follows the way input arrays work.

useContext

Similar to the Context mentioned before

const value = useContext(MyContext);

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 value prop of < mycontext. Provider > closest to the current component in the upper component

const themes = {
  light: {
    foreground: "#000000",
    background: "#eeeeee"
  },
  dark: {
    foreground: "#ffffff",
    background: "#222222"
  }
};

const ThemeContext = React.createContext(themes.light);

function App() {
  return (
    <ThemeContext.Provider value={themes.dark}>
      <Toolbar />
    </ThemeContext.Provider>
  );
}

function Toolbar(props) {
  return (
    <div>
      <ThemedButton />
    </div>
  );
}

function ThemedButton() {
  const theme = useContext(ThemeContext);

  return (
    <button style={{ background: theme.background, color: theme.foreground }}>
      I am styled by theme context!
    </button>
  );
}

useContext Argument to must be context Object itself

useReducer

const [state, dispatch] = useReducer(reducer, initialArg, init);

Receive a reducer with the shape (state, action) = > newstate, and return the current state and its matching dispatch method.

Similar to redux.

Implemented counters

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 App() {
  const [state, dispatch] = useReducer(reducer, initialState);
  return (
    <>
      Count: {state.count}
      <button onClick={() => dispatch({ type: "decrement" })}>-</button>
      <button onClick={() => dispatch({ type: "increment" })}>+</button>
    </>
  );
}

Specify the initial state

const [state, dispatch] = useReducer(
    reducer,
    {count: initialCount}
  );

lazy initialization

You can choose to create the initial state lazily. To do this, you need to pass in the init function as the third parameter of useReducer, so that the initial state will be set to init(initialArg).

function init(initialCount) {
  return {count: initialCount};
}

function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return {count: state.count + 1};
    case 'decrement':
      return {count: state.count - 1};
    case 'reset':
      return init(action.payload);
    default:
      throw new Error();
  }
}

function App({initialCount}) {
  const [state, dispatch] = useReducer(reducer, initialCount, init);
  return (
    <>
      Count: {state.count}
      <button
        onClick={() => dispatch({type: 'reset', payload: initialCount})}>

        Reset
      </button>
      <button onClick={() => dispatch({type: 'decrement'})}>-</button>
      <button onClick={() => dispatch({type: 'increment'})}>+</button>
    </>
  );
}

Skip dispatch

If the return value of Reducer Hook is the same as the current state, React will skip the rendering of subcomponents and the execution of side effects.

React uses the Object.is comparison algorithm to compare state

useCallback

When the inline callback function and dependency array are passed into useCallback as parameters, it will return the remembered version of the callback function, which will be updated only when a dependency changes. It's useful when you pass a callback function to an optimized subcomponent that uses referential equality to avoid unnecessary rendering, such as shouldComponentUpdate.

const memoizedCallback = useCallback(
  () => {
    doSomething(a, b);
  },
  [a, b],
);

useRef

useRef returns a variable ref object whose. current property is initialized to the passed in parameter (initialValue). The returned ref object remains unchanged throughout the life of the component.

It's similar to the previous ref,forwardref,createref, except that it's in the function component.

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

useMemo

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

Pass the create function and dependency array as parameters to useMemo, which recalculates the remembered value only when a dependency changes. This optimization helps to avoid high overhead calculations every time you render.

Similar to memo

Other API

It's almost the same without a narrative.

https://zh-hans.reactjs.org/d...

Posted by abhi201090 on Wed, 16 Oct 2019 02:02:12 -0700