React Redux is a common component in react ecology, which can simplify the Redux process. (note the concepts: react, Redux and react Redux are three different things)
1. Install react Redux dependency
npm install --save react-redux
2. < provider > provider
< provider > is a provider. As long as this component is used, all other components in the component can use store, which is also the core component of react redux
import React from 'react'; import ReactDOM from 'react-dom'; import TodoList from './TodoList' import { Provider } from 'react-redux' import store from './store' //Declare an App component, and then wrap the component with a Provider. const App = ( <Provider store={store}> <TodoList /> </Provider> ) ReactDOM.render(App, document.getElementById('root'));
3. connect connector
React Redux provides a connect method to connect mapStateToProps, mapDispatchToProps and components
1)TodoList.js component into connect
import { connect } from 'react-redux';
2) Mapping relation making
The mapping relationship is to map the original state to the props attribute in the component
mapStateToProps
const mapStateToProps = (state) => { return { inputValue : state.inputValue, list: state.list, } }
mapDispatchToProps
const mapDispatchToProps = (dispatch) => { return { getTodoList() { const action = getTodoListAction(); dispatch(action); }, inputChange(e) { const action = changeInputAction(e.target.value); dispatch(action); }, clickButton() { const action = addItemAction(); dispatch(action); }, deleteItem(index) { const action = deleteItemAction(index); dispatch(action); } } }
Because react Redux does not support asynchronous operations, you need to introduce the middleware Redux thunk to support asynchronous operations
In the TodoList case, it is useful to obtain the List operation when the component is loaded (in the actual project, the DataSource in the List is the default result obtained from the back end. Here, a false data is simulated for convenience)
Front end Mock false data
Create a new getList folder under the public folder, and a new mock under the getList folder JSON file
mock.json file
{ "list":[ "Get up at 4 a.m. and exercise", "Swimming after work for an hour at noon", "From 8 p.m. to 10 p.m., study for two hours" ] }
store folder
Generally, the store folder is divided into reducer js index.js constants. JS (or actionTypes.js) and actioncreators js
First, to obtain data, the component will first create an action, which is an object containing the type (i.e. actionType) and value of the action, and then the store will distribute the action. After receiving the action, the store will give it to the reducer JS, where the default data and processed data are stored. After the reducer processes the data, it returns a new state to the store; Then, the component needs to obtain the new state. Generally, the function store is obtained through setstate; Set the state of the current component; this. setState(store.getState())
index.js
This introduces Redux thunk middleware
import {createStore, applyMiddleware, compose} from 'redux'; import reducer from './reducer'; //Introduction of ruducer import thunk from 'redux-thunk'; // Using compose to create a compose enhancement function is equivalent to establishing a chain function const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({}) : compose; // Enhancement function combined with thunk const enhancer = composeEnhancers(applyMiddleware(thunk)) // Create a data warehouse const store = createStore(reducer, enhancer) export default store;
actionTypes.js
All action s of the TodoList case are stored here
export const CHANGE_INPUT = 'changeInput'; export const ADD_ITEM = 'ADD_ITEM'; export const DELETE_ITEM = 'DELETE_ITEM'; export const GET_LIST = 'GET_LIST';
actionCreators.js
This corresponds to all action processing methods
import { CHANGE_INPUT, ADD_ITEM, DELETE_ITEM, GET_LIST } from "./actionTypes"; import axios from 'axios'; export const changeInputAction = (value) => ({ type: CHANGE_INPUT, payload: value }) export const addItemAction = () => ({ type: ADD_ITEM, }) export const deleteItemAction = (index) => ({ type: DELETE_ITEM, payload: index }) export const getListAction = (data) => ({ type: GET_LIST, payload: data }) export const getTodoListAction = () =>{ return (dispatch) => { axios.get('/getList/mock.json') .then((res) => { const data = res.data; const action = getListAction(data); dispatch(action); }) } }
reducer.js
This corresponds to a business processing logic of action
import { CHANGE_INPUT, ADD_ITEM, DELETE_ITEM, GET_LIST } from './actionTypes' const defalutState = { inputValue : 'Write Something', list :[] } export default (state = defalutState, action) =>{ if (action.type === CHANGE_INPUT) { let newState = JSON.parse(JSON.stringify(state)); newState.inputValue = action.payload; return newState; } if (action.type === ADD_ITEM) { let newState = JSON.parse(JSON.stringify(state)); newState.list.push(newState.inputValue); newState.inputValue = ''; return newState; } if (action.type === DELETE_ITEM) { let newState = JSON.parse(JSON.stringify(state)); newState.list.splice(action.payload, 1); return newState; } if(action.type === GET_LIST){ //Write business logic according to the type value let newState = JSON.parse(JSON.stringify(state)) newState.list = action.payload.list //Duplicate List array return newState } return state }
The class component implements the TodoList case in combination with the componentDidMount life cycle
TodoList.js
// eslint-disable-next-line import React, { Component } from 'react'; import { connect } from 'react-redux'; import { Input, Button, List } from '../../../redux3-redux-thunk/node_modules/antd/lib'; import { getTodoListAction, changeInputAction, addItemAction, deleteItemAction } from './store/actionCreators'; import 'antd/dist/antd.css'; // class component writing class TodoList extends Component { componentDidMount() { this.props.getTodoList() } render() { const { inputValue, inputChange, clickButton, list, deleteItem } = this.props; return ( <div style={{margin: "10px"}}> <div> <Input value={inputValue} onChange={inputChange} style={{ width:'250px', marginRight:'10px'}}/> <Button type="primary" onClick={clickButton}>increase</Button> </div> <div style={{margin:'10px',width:'300px'}}> <List bordered dataSource={list} renderItem={(item, index)=>(<List.Item key={index} onClick={() => deleteItem(index)}>{item}</List.Item>)} /> </div> </div> ); } } const mapStateToProps = (state) => { return { inputValue : state.inputValue, list: state.list, } } const mapDispatchToProps = (dispatch) => { return { getTodoList() { const action = getTodoListAction(); dispatch(action); }, inputChange(e) { const action = changeInputAction(e.target.value); dispatch(action); }, clickButton() { const action = addItemAction(); dispatch(action); }, deleteItem(index) { const action = deleteItemAction(index); dispatch(action); } } } export default connect(mapStateToProps, mapDispatchToProps)(TodoList);
Implementation of TodoList with stateless components and hooks
import React, { useEffect } from 'react'; import { connect } from 'react-redux'; import { Input, Button, List } from '../../../redux3-redux-thunk/node_modules/antd/lib'; import { getTodoListAction, changeInputAction, addItemAction, deleteItemAction } from './store/actionCreators'; import 'antd/dist/antd.css'; // Stateless component writing const TodoList = (props) => { const { inputValue, inputChange, clickButton, list, deleteItem, getTodoList } = props; useEffect(() => { getTodoList() },[])// eslint-disable-line react-hooks/exhaustive-deps return ( <div style={{margin: "10px"}}> <div> <Input value={inputValue} onChange={inputChange} style={{ width:'250px', marginRight:'10px'}}/> <Button type="primary" onClick={clickButton}>increase</Button> </div> <div style={{margin:'10px',width:'300px'}}> <List bordered dataSource={list} renderItem={(item, index)=>(<List.Item key={index} onClick={() => deleteItem(index)}>{item}</List.Item>)} /> </div> </div> ) } const mapStateToProps = (state) => { return { inputValue : state.inputValue, list: state.list, } } const mapDispatchToProps = (dispatch) => { return { getTodoList() { const action = getTodoListAction(); dispatch(action); }, inputChange(e) { const action = changeInputAction(e.target.value); dispatch(action); }, clickButton() { const action = addItemAction(); dispatch(action); }, deleteItem(index) { const action = deleteItemAction(index); dispatch(action); } } } export default connect(mapStateToProps, mapDispatchToProps)(TodoList);
TodoList case run:
If you want to further understand the process of react Redux, you can debug it through the Redux DevTools tool