Redux: If you don’t know if you need Redux, you don’t need it.

Redux, similar to Vuejs’ Vuex, is the react data management center.

  • Redux started

    • First we need to install Redux

      npm install redux --save
      Copy the code
  • Store

    The first thing we need to understand in Redux is the store, which is the commissar that helps us manage our data, and the store is where the data is stored, you can think of it as a container. There can only be one Store for the entire app.

  • State

    The Store object contains all the data. If you want data at a point in time, take a snapshot of the Store. This collection of data at this point in time is called State. The current State can be obtained from store.getState()

  • Action

    If the State changes, the View changes. However, the user cannot change the State directly, only the View, so State changes must be caused by the View. An Action is a notification from the View that the State should change.

    Action is an object. The type attribute is required and represents the name of the Action.

  • Dispatch

    The functionality is that in order for our View layer to issue an Action, it has to be triggered by dispatch

  • Reducer

    When the Store receives the Action, it must give a new State for the View to change. This State calculation process is called Reducer.

    Reducer is a function that takes Action and the current State as parameters and returns a new State.

  • Popular understanding of redux

    Take our * east as an example, all shipments are sent from the warehouse, which is the store of Redux. The state in store is to store data, namely goods equivalent to the warehouse. When we place an order from * East software, we trigger a dispatch, and then * East background receives the order notification (action) warehouse. Rather we place an order to buy the goods reach the warehouse (this process is that we cannot direct contact and goods, if you can contact the goods would have to steal light ha ha ha), after notice to the warehouse, warehouse is punctuated with workers (reducer) a series of actions to deal with delivery, send out the goods after the warehouse the goods data (state) data is changed, The goods arrive in our hands (the view changes)

  • Simple addition and subtraction button implementation
    // store.js import {createStore} from 'redux' const counterReducer = (state=0,action)=>{// Set default value switch (action.type) {  case 'add': return state+1 ; Case 'minus': return state-1; default: return state } }; const store = createStore(counterReducer); export default storeCopy the code
    // app.js class App extends Component {render() {return (<div className="App"> {/*getState() returns the current state tree which is the last one in the store The reducer return value is the same. * /} < p > {store. GetState ()} < / p > < Button type = {} "primary" onClick = {() = > store. Dispatch ({type: "add"})} > add + < / Button > < Button Type = {} "primary" onClick = {() = > store. Dispatch ({type: "minus"})} > reduce - < / Button > < / div >). }}Copy the code
    // the render method in index.js needs to manually subscribe to listen import store from "./store"; const render =()=>{ ReactDOM.render( <App />, document.getElementById('root') ); }; render(); store.subscribe(render); // Every time the state changes, we need to render onceCopy the code
  • react-redux

    Use react-redux instead of manually listening

    npm insatll react-redux --save
    Copy the code
    • Provider top-level components to provide data,
    • Connect high-level components that provide data and methods, map component state to properties, and then call only props
    • See how react-Redux does this.
    Import store from "./store"; import store from "./store"; Import {Provider} from 'react-redux' reactdom. render <Provider store={store}> <App /> </Provider>, document.getelementById ('root'));Copy the code

    The Provider passes the data in and uses connect links wherever you want to use the data, so the App and redux are connected

    // app.js class App extends Component { render() { return ( <div className="App"> <p>{this.props.num}</p> // dispatch <Button type={"primary"} onClick={()=>this.props. Add ()}> add +</Button> <Button type={"primary"} The onClick = {() = > this. Props, minus ()} > reduce - < / Button > < / div >). }} const mapStateToProps = (state) =>{this.props return {num:state}}; const mapDispatchToProps = dispatch=>{ return{ add:()=>dispatch({type:"add"}), minus:()=>dispatch({type:"minus"}) } } App = connect(mapStateToProps,mapDispatchToProps)(App)Copy the code
  • Connect in React-redux is written as a decorator

    Connect uses a higher-level component to declare data and methods in the required state

    app.js@connect (// Es6 syntax //state=>({num:state}), // Read data state=>{return {num:state}}, // Synchronous dispatches can be shortened to write data, the dispatches to be called, and these methods are passed to props // add ()=>({type:"add", step:2}), can pass multiple arguments, But the first argument is a request to modify the data {add ()=>({type:"add"}), minus:()=>({type:"minus"}) } // dispatch=>{ // return{ // add:()=>dispatch({type:"add"}), // minus:()=>dispatch({type:"minus"}) // } // } )Copy the code
  • Redux defaults to synchronous operations, so asynchronous tasks need to use itThe middlewareTo complete the

    Why can asynchronous tasks only be done through middleware?

    1. Reducer: pure function, can only undertake the function of calculating State, not suitable for other functions, theoretically pure function cannot do read and write operations
    2. View: corresponds to State one by one, which can be regarded as the visual layer of State and is not suitable for other functions
    3. Action: The object storing data, namely the message carrier, can only be controlled by others, and cannot perform any operations on itself
    4. The actual Reducer and action store both need to split files independently

    Therefore, dispatch requests for asynchronous tasks need to be processed by middleware before they reach the Reducer.

    Let’s try redux-Logger and Redux-thunk (asynchronous operation) middleware

    / / store. Js import {createStore, applyMiddleware} from the 'story' / / applyMiddleware is to use middleware import logger from 'story - logger' Import thunk from 'redux-thunk' const counterReducer = (state=0,action)=>{// Set default value switch (action.type) {case 'add': return state+1 ; case 'minus': return state-1 ; default: return state } }; const store = createStore(counterReducer,applyMiddleware(logger,thunk));Copy the code
    @connect( state=>{ return { num:state } }, { add:()=>({type:"add"}), minus:()=>({type:"minus"}), AsyncAdd ()=> Dispatch =>{// Delay increases by 1. Simulation of asynchronous task setTimeout () = > {dispatch ({type: "add"})}, 2000)}})Copy the code
  • Multiple reducer
    //store.js import {createStore,applyMiddleware,combineReducers} from 'redux' const store = createStore( CombineReducers ({counterReducer, numberReducer}), / / if we have a numberReducer applyMiddleware (logger, thunk)); export default storeCopy the code
  • Remove the Reducer and Action
    Redux.js const counterReducer = (state=0,action)=>{// Set the default value switch (action.type) {case 'add': return state+1 ; case 'minus': return state-1 ; default: return state } }; const add= ()=>({type:"add"}); const minus=()=>({type:"minus"}); Thunk const asyncAdd =()=>dispatch=>{setTimeout(()=>{dispatch({type:"add"})},2000)}; export {counterReducer,add,minus,asyncAdd}Copy the code
    import {Provider} from 'react-redux' import * as serviceWorker from './serviceWorker'; import {createStore,applyMiddleware} from 'redux' import logger from 'redux-logger' import thunk from 'redux-thunk' import {counterReducer} from "./couter.redux"; / / new store first parameter reducer for the second parameter middleware const store = createStore (counterReducer, applyMiddleware (logger, thunk)); //import store from "./store"; Reactdom.render (// Provider, <Provider store={store}> <App /> </Provider>, document.getelementById ('root'));Copy the code
    Import {add,minus,asyncAdd} from "./couter.redux"; @connect( state=>{ return { num:state } }, {add,minus,asyncAdd} // )Copy the code