1. How Redux works

1. What is it? Redux is a solution for communication and state sharing between components. This reducer consists of three parts: Store Action

  • Store is the object that stores the current state of react. Store changes drive the React lifecycle, causing the page state to change
  • Action: is the only way to change state. Action is an object. There are two parts, one is the type, and the other is the payload
  • Reducer: The reducer: action’s handler, which returns a new state. Used to modify state in store. Phi is a pure function

Scenario: 1. User operations are cumbersome, resulting in a stateful dependency between components

2. Process:

The actions and Store are triggered and the reducer is automatically called. The reducer returns a new state.

react-redux

Three principles: Single data source:

Hand write a simplified version of Redux, see bottom

3, combineReducers

Use to merge multiple reducer functions

import {combineReducers} from 'redux'
import cartReducer from './cartList'
export default combineReducers({
    cartReducer,
    otherReducer		
});
Copy the code

4. React-redux implementation principle

No need to pass layers of props through store, no need to manually subscribe, no need to dispatch tedious writing

Redux is a common module used to handle state changes in applications. React-redux can be used to combine the two modules in react +Redux projects. React-redux is a lightweight wrapper library implemented through two core methods:

Provider: Encapsulates the entire application from the outside and passes the Store to the Connect module.

Connect:

1. Wrap the original component, passing state and action inside the original component as props. 2. Listen for store Tree changes so that the original component it wraps can respond to state changesCopy the code
import { connect } from 'react-redux'
import { increment, decrement, reset } from './actionCreators'

// const Counter = ...

const mapStateToProps = (state /*, ownProps*/) = > {
  return {
    counter: state.counter,
  }
}

const mapDispatchToProps = { increment, decrement, reset }

export default connect(mapStateToProps, mapDispatchToProps)(Counter)
Copy the code

4.1 the connect

The connect method has four parameters. The first parameter is mapStateToProps, which is used to inject state into the props of the current component from the store

The second parameter can be mapDispatchToProps. The main function of this parameter is to inject the methods generated by the action into the props of the current component.

Method 2: In this case, the object is called actionCreators. Once the actionCreators is passed in, it is called in the component through this.props. ActionCreator. In this case, after the call, That Action Creator will automatically dispatch its internal actions for you

But if it’s an asynchronous action, you don’t return anything, you don’t dispatch, you get an error, you need asynchronous middleware to handle it, you generate a new action, you dispatch it manually

export const increment = (id) = > {
  return {
    type: actionType.CART_AMOUNT_INCREMENT,
    payload: {
      id
    }
  }
}
Copy the code
import { connect } from 'react-redux'
import { increment, decrement, reset } from './actionCreators'

// const Counter = ...

const mapStateToProps = (state /*, ownProps*/) = > {
  return {
    counter: state.counter,
  }
}

const mapDispatchToProps = { increment, decrement, reset }

export default connect(mapStateToProps, mapDispatchToProps)(Counter)
Copy the code
<button onClick={this.props.decrement.bind(this, item.id)}>-</button>
Copy the code

5. Asynchronous Action

export const decrementAsync = (id) = > {
  setTimeout(() = > {
    return {
      type: actionType.CART_AMOUNT_DECREMENT,
      payload: {
        id
      }
    };
  })
}
<button onClick={this.props.decrementAsync.bind(this, item.id)}> Delay subtraction1</button> redux.js:192 Uncaught Error: Actions must be plain objects. Use custom middleware for async actions.
Copy the code

Story – thunk middleware

import { createStore, applyMiddleware } from 'redux'
import thunk from 'redux-thunk'
import rootReducer from './reducers'
export default createStore(rootReducer, applyMiddleware(thunk))

actions/cart.js
// Async action, using redux-thunk, returns a method in actionCreator that takes dispatch
export const decrement = (id) = > {
  return {
    type: actionType.CART_AMOUNT_DECREMENT,
    payload: {
      id
    }
  }
}
// export const decrementAsync = (id) => {
// return (dispatch) => {
// setTimeout(() => {
// dispatch(decrement(id))
/ /}, 2000)
/ /}
// }
export const decrementAsync = id= > dispatch= > {
  setTimeout(() = > {
    dispatch(decrement(id))
  }, 2000<button onClick={this.props.decrementAsync.bind(this, item.id)}> Delay subtraction1</button>
Copy the code

Write a simple redux by hand

const countState = {
    count: 100
};


const reducer = (state, action) = > {
    console.log('action',action)
    if(! state) { state = countState }switch(action.type) {
        case 'jian': 
            return {
                ...state,
                count: state.count - action.n
            };
        case 'jia':
            return {
                ...state,
                count: state.count + action.n
            };
        default:
            return state
    }
};

const createStore = (reducer) = > {
    let state = null;
    const getState = () = > state;
    const listeners = [];
    const subscribe = listener= > listeners.push(listener);
    const dispatch = (action) = > {
        state = reducer(state, action);
        RenderCount may not be called, but other states may not be called
        // renderCount();
        listeners.forEach(listener= > listener());
    };
    dispatch({});
    return {
        getState,
        dispatch,
        subscribe
    }
}
const store = createStore(reducer);
// const store = Redux.createStore(reducer);
*** The reducer method changes state and returns a new state
// *** Add reducer to createStore
const renderCount = () = > {
    document.getElementById('count').innerHTML = store.getState().count
};
renderCount();
store.subscribe(renderCount);
Copy the code