Contents of series of articles:
Redux Basic Application: juejin.cn/post/691501…
Redux: Asynchronous Action and Middleware: juejin.cn/post/691504…
Redux reacts-Redux (todolist) : juejin.cn/post/691504
I. Component classification
React-redux divides all components into two broad categories: UI components (Presentational Components) and container Components (Container Components).
UI components:
- Only responsible for the presentation of the UI, with no business logic
- No state (that is, the this.state variable is not used)
- All data is provided by the parameter (this.props)
- Do not use any of Redux’s apis
Container components:
- Responsible for managing data and business logic, not UI rendering
- With internal state, you can give state to child components via props
- Use Redux’s API
React-redux specifies that all UI components are provided by the user, while container components are automatically generated by React-Redux. That is, we only write UI components, and the top-level container is generated by calling a method. How? Keep looking.
Connect () method
React-redux provides the Connect method for wrapping UI components into container components. However, as we mentioned earlier, the top-level container needs to have state and business logic, so when the CONNECT method generates the top-level container, we should define the required state and business logic and provide it to Connect. Thus, the complete API for the CONNECT method is as follows.
import { connect } from 'react-redux'
const VisibleTodoList = connect(
mapStateToProps,
mapDispatchToProps
)(TodoList)
Copy the code
The connect method accepts two parameters: mapStateToProps and mapDispatchToProps. They define the business logic of the UI components. The former is responsible for the input logic, which maps state to the UI component’s parameters (props), and the latter is responsible for the output logic, which maps user actions on the UI component to actions.
The mapStateToProps() method
MapStateToProps is a function. It establishes a mapping between the (external) state object and the (UI component’s) props object. Mapping a portion of the useful state to the props of the current container component so that it can be referenced directly by the props.
MapStateToProps subscribes to the Store, and every time state is updated, it automatically recalculates the PARAMETERS of the UI component, triggering a re-rendering of the UI component.
As a function, mapStateToProps should return an object in which each key-value pair is a mapping. Look at the following example:
// Take some state for the current top-level container
const mapStateToProps = (state) = > {
return {
todos: getVisibleTodos(state.todos, state.visibilityFilter)
}
};
// Calculate the status based on the toDOS and visibilityFilter values, mapping to the props of the current container
const getVisibleTodos = (todos, filter) = > {
switch (filter) {
case 'SHOW_ALL':
return todos;
case 'SHOW_COMPLETED':
return todos.filter(t= > t.complete);
case 'SHOW_ACTIVE':
return todos.filter(t= >! t.complete);default:
throw new Error('Unknown filter: ' + filter)
}
};
Copy the code
Todos can be used to get the desired state value directly, and the container is rerendered when the toDOS changes.
Method mapDispatchToProps(
MapDispatchToProps is the second parameter to the connect function that maps UI component parameters to the Store. dispatch method. That is, it defines which user actions should be passed to the Store as actions. An Action can be a function or an object. To dispatch an action, just call the method under this.props to call Dispatch.
// Bind the event to props, and call the props. When the event is called, the action can be sent directly to the store to modify the state
const mapDispatchToProps = (
dispatch
) = > {
return {
setFilter: (filter) = > {
dispatch({
type: 'SET_VISIBILITY_FILTER'.filter: filter
});
},
addTodo: (content) = > {
dispatch({
type: 'ADD_TODO'.content: content,
id:i++
});
},
toggleTodo: (id) = >{
dispatch({
type: 'TOGGLE_TODO'.id: id }); }}; };Copy the code
As we know, redux one-way data flow needs store, Action, dispatch and reducer. So far, store has not appeared, please continue to look down.
Four, components,
When the connect method generates the container component, we define a bunch of logic and states that only make sense if the top container can get to the Store, so we need the container component to get to the Store state object.
React-redux provides a Provider component that allows any container component in the component tree to get state.
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import { Provider } from 'react-redux';
import { createStore } from 'redux';
import reducers from "./redux/reducers";
let store = createStore(reducers);
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>.document.getElementById('root'));Copy the code
5. Examples: TodoList
The classic TodoList renderings are as follows:
Let’s look at the project structure:
Provider wraps the component in index.js with the following code:
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import { Provider } from 'react-redux';
import { createStore } from 'redux';
import reducers from "./redux/reducers";
let store = createStore(reducers);
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>.document.getElementById('root'));Copy the code
Folder Description
SRC >containers>TodoList– top layer container folder, SRC >containers>TodoList> todolist.js — top layer container component, SRC >containers>TodoList> Components –UI components folder, below which is the UI components file, SRC >redux>reducers– used to construct the reducer function of the store,
TodoList:
import React, { Component } from 'react'; import AddTodo from './components/AddTodo' import VisibleTodoList from './components/VisibleTodoList' import Filter from './components/Filter' import {connect} from "react-redux"; let i=0; class TodoList extends Component { constructor(props){ super(props); } render() { return ( <div> <AddTodo addTodo={this.props.addTodo} /> <VisibleTodoList todos={this.props.todos} toggleTodo={this.props.toggleTodo}/> <Filter setFilter={this.props.setFilter}/> </div> ); Const mapStateToProps = (state) => {return {todos: const mapStateToProps = (state) => {return {todos: getVisibleTodos(state.todos, state.visibilityFilter) } }; // Calculate the status according to the toDOS and visibilityFilter values, Props const getVisibleTodos = (todos, filter) => {switch (filter) {case 'SHOW_ALL': return todos; case 'SHOW_COMPLETED': return todos.filter(t => t.complete); case 'SHOW_ACTIVE': return todos.filter(t => ! t.complete); default: throw new Error('Unknown filter: ' + filter) } }; Const mapDispatchToProps = (dispatchToprops) => {return {setFilter: // Const mapDispatchToProps = (dispatchToprops) => {return {setFilter: (filter) => { dispatch({ type: 'SET_VISIBILITY_FILTER', filter: filter }); }, addTodo: (content) => { dispatch({ type: 'ADD_TODO', content: content, id:i++ }); }, toggleTodo: (id)=>{ dispatch({ type: 'TOGGLE_TODO', id: id }); }}; }; export default connect(mapStateToProps, mapDispatchToProps)(TodoList);Copy the code
The full code can be viewed at: github.com/Amy-Tong126…