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