Learn the three Hooks apis first

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

UseState alternative, which receives a Reducer of the form (state, action) => newState and returns the current state and the dispatch method that matches it

  1. useEffect

The function assigned to useEffect is delayed after the component is rendered to the screen. By default, effect will be executed at the end of each render round, but you can choose to have it executed only when certain values change.

  1. useLayoutEffect

Its 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 internal update schedule is refreshed synchronously before the browser performs the drawing.

import React, {useReducer, useLayoutEffect, useEffect} from "react"; import {counterReducer} from ".. /store"; Const init = initArg => {// Change the initial value passed in, in this case string to int return initarg-0; }; export default function HooksPage(props) { const [state, dispatch] = useReducer(counterReducer, "0", init); useEffect(() => { console.log("useEffect"); //sy-log }); useLayoutEffect(() => { console.log("useLayoutEffect"); //sy-log }); console.log("---"); //sy-log return ( <div> <h3>HooksPage</h3> <p>{state}</p> <button onClick={() => dispatch({type: "ADD"})}>add</button> </div> ); }Copy the code

Use the react – story

yarn add react-redux
Copy the code

Two apis are provided :(provider,connect)

connect

Provide data and change methods for components (connect the React component to the Redux Store. Returns a new component class connected to the Redux Store.

mapStateToProps(state,ownProps)

  1. The callback must return a pure object that is merged with the component’s props. If this parameter is defined, the component will listen for changes to the Redux store, otherwise it will not.
  2. OwnProps is the props of the current component. If specified,mapStateToProps will be called whenever the component receives new PEOPS,mapStateToProps will be recalculated, and mapDispatchToProps will be called. So to avoid some performance issues, we usually don’t pass the ownProps parameter.

mapDispatchToProps(dispatch,ownProps),

  1. If this parameter is omitted, by default, Dispatch is injected into props.
  2. If you pass an object, each function defined on that object is treated as Redux Action Creator, with the method name defined by the object as the property name. Each method returns a new function that takes the return value of Action Creator as an argument. These properties are incorporated into the props of the component.
  3. If you pass a function, the function will receive a function, and you will then decide how to return an object.

OwnProps is the props of the current component. If this is specified, mapDispatchToProps is invoked whenever the component receives new props. Pay attention to performance!

mergeProps(stateProps, dispatchProps, ownProps)

  1. If this parameter is specified, the results of the execution of mapStateToProps() and mapDispatchToProps() and the props of the component itself are passed into the callback function. The object returned by this callback function will be passed to the wrapped component as props.
connect([mapStateToProps],[mapDispatchToProps],[mergeProps],[options])
Copy the code

Step 1: Provider provides store for descendant components and store- index.js globally

import React from "react"; import ReactDOM from "react-dom"; import "./index.css"; import App from "./App"; import {Provider} from "react-redux"; import store from "./store/"; // Put the Provider outside the root component, Render (<Provider store={store}> <App /> </Provider>, document.getelementByid ("root"));Copy the code

Step 2: Get the status data – reactreduxPage.js

import React, { Component } from "react"; import { connect } from "react-redux"; class ReactReduxPage extends Component { render() { const { num, add, minus, asyAdd } = this.props; return ( <div> <h1>ReactReduxPage</h1> <p>{num}</p> <button onClick={add}>add</button> <button onClick={minus}>minus</button> </div> ); } } const mapStateToProps = state => { return { num: state, }; }; const mapDispatchToProps = { add: () => { return { type: "add" }; }, minus: () => { return { type: "minus" }; }}; Export default connect(mapStateToProps mapDispatchToProps, // issue event mapping)(ReactReduxPage);Copy the code

Step 3: Use details

// Note that export default connect()() is used. Usually do in the project will break up using the export default connect (mapStateToProps mapDispatchToProps) (Component) import React, {Component} from "react"; import {connect} from "react-redux"; import {bindActionCreators} from "redux"; // Connect the React component to the store, returns a new component class (HOC) export default connect(// mapStateToProps Fucntion //! Define ownProps carefully, because if you define ownProps, the current mapStateToProps will be called whenever the ownProps change, //! State => {// console.log("mapStateToProps"); //sy-log return { count: state }; } / / mapDispatchToProps receiving Object | | Fucntion / / the Object at this time no dispacth props, but with the action creators, Internal implementation dispatch / / / / {/ / add: () = > ({type: "add"}), / / minus: () = > ({type: "MINUS"}) // / The Fucntion parameter is dispatch with ownProps //! Define ownProps carefully, because once you define ownProps, the current mapStateToProps will be called whenever the ownProps change, Easy to affect performance (dispatch, ownProps) => {console.log("mapDispatchToProps--", ownProps); //sy-log let creators = { add: payload => ({type: "ADD", payload}), minus: () => ({type: "MINUS"}) }; creators = bindActionCreators(creators, dispatch); return {dispatch, ... creators}; } )( class ReactReduxPage extends Component { add = () => { this.props.dispatch({type: "ADD"}); }; render() { console.log("props", this.props); //sy-log const {count, dispatch, add, minus} = this.props; return ( <div> <h3>ReactReduxPage</h3> <p>omg:{count}</p> <button onClick={this.add}>add-use dispatch</button> <button onClick={() => add(100)}> add</button> <button onClick={minus}>minus</button> </div> ); }});Copy the code

Implement the react – story

Higher-order components implement the CONNECT method

import React, {useContext, useEffect, useReducer, useLayoutEffect} from "react"; // Provider in index.js, passes store, uses context so that all child components have a chance to receive store const context = react.createcontext (); / / implementation: connect (({count}) = > ({count}), {add: () = > ({type: 'ADD})})(Cmp) export const connect = ( mapStateToProps = state => state, MapDispatchToProps) => WrappedComponent => props => {// read store state const store = useContext(Context); const {getState, dispatch, subscribe} = store; const stateProps = mapStateToProps(getState()); // dispatch object | function let dispatchProps = {dispatch}; if (typeof mapDispatchToProps === "function") { dispatchProps = mapDispatchToProps(dispatch); } else if (typeof mapDispatchToProps === "object") { dispatchProps = bindActionCreators(mapDispatchToProps, dispatch); Const [forceUpdate] = useReducer(x => x + 1, 0); const [forceUpdate] = useReducer(x => x + 1, 0); // useLayoutEffect is used here. In order to update the subscription in real time, instead of delayed, the return implements the unsubscription after the subscription. [store] associated data useLayoutEffect(() => {const unsubscribe = subscribe(() => {// Store state changes forceUpdate is mandatory update forceUpdate(); }); return () => { if (unsubscribe) { unsubscribe(); }}; }, [store]); return <WrappedComponent {... props} {... stateProps} {... dispatchProps} />; }; // The state dispatch subscribe export function Provider({store, children}) { return <Context.Provider value={store}>{children}</Context.Provider>; } function bindActionCreator(creator, dispatch) { return (... args) => dispatch(creator(... args)); } export function bindActionCreators(creators, dispatch) { const obj = {}; for (let key in creators) { obj[key] = bindActionCreator(creators[key], dispatch); } return obj; }Copy the code

React-redux hooks API and implementation

  1. UseSelector gets the data
  2. UseDispatch for dispatch
export function useSelector(selector) { const store = useStore(); const {getState, subscribe} = store; const selectedState = selector(getState()); Const [forceUpdate] = useReducer(x => x + 1, 0); // useLayoutEffect is used to explain the hook. UseLayoutEffect (() => {const unsubscribe = subscribe(() => {// Store state changes forceUpdate is mandatory update forceUpdate(); }); return () => { if (unsubscribe) { unsubscribe(); }}; }, [store]); return selectedState; } export function useDispatch() { const store = useStore(); return store.dispatch; } function useStore() { const store = useContext(Context); return store; }Copy the code

React-router Is used to customize hooks

import React, {useCallback} from "react"; import {useSelector, useDispatch} from ".. /ReactRedux"; Export default function ReduxHooksPage(props) {const count = useSelector(({count}) => count); Const dispatch = useDispatch(); // [] as the dependency list of useCallback. This ensures that callback will not change when rendering again, so React will not call it unnecessarily. // useMemo cache for parameters, useCallback cache for functions, Const add = useCallback(() => {dispatch({type: "add "}); } []); return ( <div> <h3>ReduxHooksPage</h3> <p>{count}</p> <button onClick={add}>add</button> </div> ); }Copy the code