What is the story
Redux is a JavaScript state container that provides predictable state management. It’s designed specifically for the React. Js framework, but it’s not only used with React, it can be used with any interface library.
Redux’s design principles
Redux is designed and implemented in accordance with three principles, or specification limits
Single data source
The transition data of the entire application is only stored in a single Store
Read-only State
The only Store is also read-only and the application cannot modify the status data directly. The API for the Store object itself is very small, with just four methods:
getState()
: Obtains the current status datadispatch(action)
: Push triggers changessubscribe(listener)
: Subscription data changesreplaceReducer(nextReducer)
:
Obviously, there is no way to set the state. The dispatch(action) is the only way to change the data, such as:
var action = {
type: 'ADD_USER'.user: {name: 'chuonye.com'}}; store.dispatch(action);Copy the code
The dispatch method passes the action to the Redux. The action is a plain object that contains the type of operation that was triggered along with the data.
Use pure functions to perform state updates
When Redux receives an action, it uses a pure function to handle it. These functions are called Reducers:
var someReducer = function(state, action) {...return state;
}
Copy the code
The Reducer accepts the current state and action as parameters. Instead of directly modifying the original data, the Reducer returns a new state to modify the data. In general, Redux is a tool that helps applications manage state data in a unified way, following a strict one-way data flow (store-read-only) design that makes the behavior of applications predictable and easy to understand.
The basic process of using Redux
Before introducing the basic use process of Redux, we implement the case of TodoList based on the native method, and then demonstrate the use process of Redux and React-Redux respectively
Native React implementation TodoList
Example:
import React, { Component } from 'react';
import {Row,Col,Button,Divider,Input,List,} from 'antd';
class TodoList extends Component {
constructor(props) {
super(props)
this.state = {
todos: ["Basketball"."Football"."Badminton"].inpVal: ""
}
}
handleChange = (e) = > {
this.setState({ inpVal: e.target.value })
}
handleClick = () = > {
const { inpVal } = this.state
let todos = this.state.todos
todos.push(inpVal)
this.setState({ todos })
}
handleDelete = (id) = > {
let {todos} = this.state
todos = todos.filter((v,index) = >index ! = id)this.setState({todos})
}
render() {
return (
<div>
<h3>React implements TodoList native</h3>
<Divider />
<Input
onChange={this.handleChange}
placeholder="Please enter"
></Input>
<Button onClick={this.handleClick}>add</Button>
<Divider />
<Row>
<Col span={6}>
<List
bordered
dataSource={this.state.todos}
renderItem={(item, index) = > (
<List.Item
extra={<a onClick={this.handleDelete.bind(this,index)}>delete</a>}
>{item}</List.Item>)}
>
</List>
</Col>
</Row>
</div>)}}export default TodoList
Copy the code
TodoList based on Redux
Install the story
yarn add redux --save
Copy the code
The concrete steps of TodoList implementation based on Redux:
- Create an Action
- Create in the root directory
action
Folder and create under the folderindex.jsx
- build
action
Function to returnaction
Object, noticeaction
Must containtype
attribute - will
action
And export
- Create in the root directory
Example:
// src/action/index.jsx
// Create an Action for Todo
const addTodoList = (iptVal) = > ({ type: 'ADD', iptVal })
// Query the current TodoList
const seleteTodoList = () = > ({ type: 'SELECT' })
/ / to monitor the Input
const InputChange = (iptVal) = > ({ type: 'INPUT', iptVal })
// Delete the Todo Action
const DeleteTodoList = (index) = > ({ type: 'DELETE', index })
module.exports = {
addTodoList,seleteTodoList,InputChange,DeleteTodoList
}
Copy the code
- Create the Reducer
- Create in the root directory
reducer
Folder and create under the folderindex.jsx
- build
reducer
, pay attention toreducer
Two parameters are to be received - The first parameter is the default and defines an initialization
state
, and then do the assignment
- Create in the root directory
Example:
/src/reducer/index.jsx
// 1. Initialization
const initState = {
todos: ["Basketball"."Football"."Badminton"].iptVal: ""
}
// 2. Create the Reducer
const reducer = (state = initState, action) = > {
let newState = Object.assign({}, state, action);
switch (action.type) {
case "ADD":
const { iptVal, todos } = state
newState.todos.push(iptVal)
return newState
case 'SELECT':
return Object.assign({}, state, action)
case 'INPUT':
return Object.assign({}, state, action)
case 'DELETE':
const { index } = action
newState.todos.splice(index, 1)
return newState
default:
returnstate; }}export default reducer
Copy the code
- Create the Store
- Create with directory
store
And create under the folderindex.jsx
- use
createStore
So the first argument in the function is going to bereducer
- The import
reducer
Set to a functioncreateStore(reducer)
- Will create the
store
To export
- Create with directory
Example:
import { createStore } from 'redux'
import reducer from '. /.. /reducer/'
const store = createStore(reducer)
export default store
Copy the code
- Redux is used in components
- Bind button to listen for events
- Passes when the component has finished loading
store
The return value can be used to register the listener - through
store.dispatch(action)
Send the action
Example:
import React, { Component } from 'react';
import {
Divider,
Input,
Button,
Row,
Col,
List
} from 'antd'
import store from '.. /.. /store/index'
import {
addTodoList,
seleteTodoList,
InputChange,
DeleteTodoList
} from '. /.. /.. /action/index'
class Home extends Component {
constructor(props) {
super(props)
this.state = store.getState()
}
componentWillMount() {
const action = seleteTodoList()
/ / send the action
store.dispatch(action)
}
handleChange = (e) = > {
const action = InputChange(e.target.value)
/ / send the action
store.dispatch(action)
}
handleClick = () = > {
const { iptVal } = this.state
const action = addTodoList(iptVal)
/ / send the action
store.dispatch(action)
}
handleDelete = (index) = > {
const action = DeleteTodoList(index)
/ / send the action
store.dispatch(action)
}
componentDidMount() {
store.subscribe(() = > this.setState(store.getState()))
}
render() {
return (
<div
style={{
width: 500.height: 500.textAlign: 'center',
margin: '0 auto'}} >
<h3>Redux implementation TodoList</h3>
<Divider />
<Input
onChange={this.handleChange}
placeholder="Please enter"
style={{ width: 300.marginRight: 50 }}
value={this.state.iptVal}
></Input>
<Button onClick={this.handleClick}>add</Button>
<Divider />
<Row>
<Col>
<List
bordered
dataSource={this.state.todos}
renderItem={(item, index) = > (
<List.Item
extra={<span onClick={this.handleDelete.bind(this, index)} >delete</span>}
>{item}</List.Item>)}
>
</List>
</Col>
</Row>
</div>)}}export default Home;
Copy the code
Summary of the Redux invocation process
Basic steps:
- create
action
- send
action
至reducer
—store.dispatch(action)
reducer(preState,action)
To process the business logicreturntostore
- Listening to the
store
Based onstore
Provided by the APIstore.getState()
Get the lateststate
action --> store.dispatch(action) --> reducer(action) --> store
Copy the code
Implement TodoList based on React-Redux
Create a project
Create-react-app demo02 CD demo02 yarn add redux -- Save yarn add react-redux -- Save yarn add antd@"^3.26.20" -- Save yarn Add the react @ "^ 16.14.0" -- saveCopy the code
Implementation steps
- Based on the
redux
buildstore
In thesrc
createstore
Directory and createindex.jsx
file - create
reducer/index.jsx
File, buildreducer
The responseaction
- through
createStore
把reducer
Injection of returnstore
- in
src/App.js
The introduction ofstore
And importProvider
Wrap the entire structure and pass it alongstore
- The introduction of
connect
To strengthen the components,mapDispatchToProps
It returns an object{key: method name,value: call Dispatch to send action}
, passed in the componentthis.props
The object can be obtained.connectBasic introduction to functions:
Parameter names | type | instructions |
---|---|---|
mapStateToProps(state,ownProps) | Function | This function willstoreAs data inpropsBind to a component state: Store in redux ownProps: props for the component |
mapDispatchToProps(dispatch,ownProps) | Function | willactionAs apropsBind to a component dispatch: is the store. The dispatch () ownProps: props for the component |
mergeProps(stateProps,dispachProps,ownProps) | Function | DispachProps and ownProps must be merged and assigned to a component. Connect uses object.assign instead of dispachProps |
options | Object | Customize the behavior of the Connector |
Build the reducer
// src/reducer/index.jsx
const initState = {
todos: ["Basketball"."Football"."Badminton"],}const rootReducer = (state = initState, action) = > {
if (action.type === "ADD") {
const { iptVal } = action
let newState = JSON.parse(JSON.stringify(state))
newState.todos.push(iptVal)
return newState
} else if (action.type === 'SELECT') {
let newState = JSON.parse(JSON.stringify(state))
return newState
} else if (action.type === "DELETE") {
const { index } = action
let newState = JSON.parse(JSON.stringify(state))
newState.todos.splice(index, 1)
return newState
} else {
return state
}
}
export default rootReducer
Copy the code
Building a store
// src/store/index.jsx
import { createStore } from "redux";
import reducer from ".. /reducer";
const store = createStore(reducer)
export default store
Copy the code
Import the Provider delivery Store
// App.jsx
import React, {
Component
} from 'react';
import {
Provider
} from 'react-redux'
import store from './store';
import AddTodo from './pages/AddTodo';
import TodoList from './pages/TodoList'
import './App.css';
class App extends Component {
render() {
return (
<div style={{ width: 500.height: 500.textAlign: 'center', margin: '0 auto' }}>
<Provider store={store}>
<h3>The React - Reudx TodoList</h3>
<AddTodo />
<br />
<TodoList />
</Provider>
</div>); }}export default App;
Copy the code
AddTodo components
import React, { Component } from 'react';
import {
Input,
Button,
} from 'antd'
import { connect } from 'react-redux'
class AddTodo extends Component {
constructor(props) {
super(props);
this.state = {
iptVal: ""
}
}
handleClick = () = > {
const { iptVal } = this.state
this.props.AddAction(iptVal)
}
render() {
return (
<div>
<Input
onChange={(e)= >This.setstate ({iptVal: e.target. Value})} placeholder=" view "style={{width: 300, default: 0.5px; default: 0.5px; default: 0.5px; default: 0.5px; default: 0.5px; 50 }} value={this.state.iptVal} ></Input>
<Button onClick={this.handleClick}>add</Button>
</div>); }}const mapDispatchToProps = (dispatch) = > {
return {
AddAction: (iptVal) = > {dispatch({type: 'ADD',iptVal})}
}
}
export default connect(null, mapDispatchToProps)(AddTodo);
Copy the code
TodoList components
import React, { Component } from 'react';
import {
Row,
Col,
List
} from 'antd'
import { connect } from 'react-redux'
class TodoList extends Component {
handleDelete = (index) = > {
this.props.RemoveAction(index)
}
render() {
return (
<div>
<Row>
<Col>
<List
bordered
dataSource={this.props.todos}
renderItem={(item, index) = > (
<List.Item
extra={<span onClick={this.handleDelete.bind(this, index)} >delete</span>}
>{item}</List.Item>)}
>
</List>
</Col>
</Row>
</div>); }}const mapStateToProps = (state) = > {
return state
}
const mapDispatchToProps = (dispatch) = > {
return {
RemoveAction: (index) = > {dispatch({type: 'DELETE',index})}
}
}
export default connect(mapStateToProps, mapDispatchToProps)(TodoList)
Copy the code
Reference:
- React-redux Chinese documentation
- TodoApp with Redux
- The react – the story’s official website