Previously, our summation case was just a component, which was played by ourselves. Next, we used multiple components to achieve data exchange between them through redux.
Step 1: Change project directory structure
src
|--containers
| |--Count
|--redux
| |--actions
| |--count.js
| |--reducers
| |--count.js
| |--constant.js
| |--store.js
|--App.jsx
|--index.js
Since we now want to share the status of multiple components, we need to divide the files into more detailed categories so that we can better maintain the project.
- futuristic
count_action.js
=become=>redux/actions/count.js
- futuristic
count_reducer.js
=become=>redux/reducers/count.js
- The corresponding import paths of other files must also be modified accordingly, so I won’t go into details here.
Step 2: Create a new Person component
document:src/containers/Person/index.jsx
import React, {
Component } from 'react'
import {
nanoid} from 'nanoid'
export default class Person extends Component {
addPerson = () => {
const {
nameNode, ageNode } = this
const person = {
id: nanoid(),
name: nameNode.value,
age: ageNode.value * 1
}
console.log(person)
}
render() {
return (
<div>
<h1>Person组件,上方组件求和为:{
this.props.sum}</h1>
<input type="text" placeholder='请输入姓名' ref={
c => this.nameNode = c} />
<input type="text" placeholder='请输入年龄' ref={
c => this.ageNode = c} />
<button onClick={
this.addPerson}>添加</button>
<h2>人员列表</h2>
<ul>
<li>姓名1--年龄</li>
</ul>
</div>
)
}
}
Then introduce it into the App component
import React, {
Component } from 'react'
// 引入Count的容器组件
import Count from './containers/Count'
import Person from './containers/Person'
export default class App extends Component {
render() {
return (
<div>
<Count/>
<hr/>
<Person/>
</div>
)
}
}
The effect is as follows:
Step 3: Write redux files related to Person component
(1). New constant type:ADD_PERSON
// src/redux/constant.js
// 该模块是用于定义action对象的type类型的常量值
export const INCREMENT = 'increment'
export const DECREMENT = 'decrement'
export const ADD_PERSON = 'add_person'
(2). Add person’s action file
// src/redux/actions/person.js
import {
ADD_PERSON } from '../constant'
// 添加人信息的action
export const createAddPersonAction = personObj => ({
type: ADD_PERSON, data:personObj})
(3). Add person’s reducer file
// src/redux/reducers/person.js
import {
ADD_PERSON} from '../constant'
const initData = [{
id:'001',name:'tom',age:18}]
export default function personReducer (preState = initData, action) {
// 获取type和data
const {
type,data} = action
switch (type) {
case ADD_PERSON:
return [data,...preState]
default:
return preState
}
}
(4). Container component integrated with Person
import React, {
Component } from 'react'
import {
nanoid} from 'nanoid'
import {
connect} from 'react-redux'
import {
createAddPersonAction} from '../../redux/actions/person'
class Person extends Component {
addPerson = () => {
const {
nameNode, ageNode } = this
const person = {
id: nanoid(),
name: nameNode.value,
age: ageNode.value * 1
}
console.log(person)
}
render() {
return (
<div>
<h1>Person组件</h1>
<input type="text" placeholder='请输入姓名' ref={
c => this.nameNode = c} />
<input type="text" placeholder='请输入年龄' ref={
c => this.ageNode = c} />
<button onClick={
this.addPerson}>添加</button>
<h2>人员列表</h2>
<ul>
<li>姓名1--年龄</li>
</ul>
</div>
)
}
}
export default connect(
state => ({
peoList:state}), // 映射状态
{
} // 映射操作状态的方法
)(Person)
At this point, we have compiled the related code of the Person
component, but it does not work now because our redux
a>. ’s store
does not use the logic in person
reducer
Step 4: Rectify the store file content
// 引入createStore,专门用于创建redux中最为核心的store对象
import {
createStore , applyMiddleware } from 'redux'
import countReducer from './reducers/count'
// 引入redux-thunk,用于支持异步action
import thunk from 'redux-thunk'
export default createStore(countReducer,applyMiddleware(thunk))
According to the code, we know that there is no Person
related reducer
introduced here, so how should we use it?
The answer is: introduce a new oneAPI
merge multiplereducer
===>combineReducers
combineReducers
is a commonly used method of combining Reducer
, which can make the code more concise and easier to maintain.
// 引入createStore,专门用于创建redux中最为核心的store对象
import {
createStore , applyMiddleware, combineReducers } from 'redux'
import countReducer from './reducers/count'
import personReducer from './reducers/person'
// 引入redux-thunk,用于支持异步action
import thunk from 'redux-thunk'
const allReducer = combineReducers({
sum: countReducer,
peoples: personReducer
})
export default createStore(allReducer,applyMiddleware(thunk))
The above is the complete version of our modified store
file. Here we use combineReducers
thisAPI
to < The /span>. this Passed to component were merged to form a new of the Count
component and the Person
reducer
allReducer
createStore
API
Step 5: Store data in redux in the Person component
import React, {
Component } from 'react'
import {
nanoid} from 'nanoid'
import {
connect} from 'react-redux'
import {
createAddPersonAction} from '../../redux/actions/person'
class Person extends Component {
addPerson = () => {
const {
nameNode, ageNode } = this
const person = {
id: nanoid(),
name: nameNode.value,
age: ageNode.value * 1
}
// console.log(person)
this.props.addPeople(person)
}
render() {
return (
<div>
<h1>Person组件</h1>
<input type="text" placeholder='请输入姓名' ref={
c => this.nameNode = c} />
<input type="text" placeholder='请输入年龄' ref={
c => this.ageNode = c} />
<button onClick={
this.addPerson}>添加</button>
<h2>人员列表</h2>
<ul>
{
this.props.peoList.map((p)=>{
return <li key={
p.id}>{
p.name}--{
p.age}</li>
})
}
</ul>
</div>
)
}
}
export default connect(
state => ({
peoList:state.peoples}), // 映射状态
{
addPeople:createAddPersonAction} // 映射操作状态的方法
)(Person)
View the effect:
Step 6: The two components introduce each other into redux, which contains state data.
document:Person/index.jsx
import React, {
Component } from 'react'
import {
nanoid} from 'nanoid'
import {
connect} from 'react-redux'
import {
createAddPersonAction} from '../../redux/actions/person'
class Person extends Component {
addPerson = () => {
const {
nameNode, ageNode } = this
const person = {
id: nanoid(),
name: nameNode.value,
age: ageNode.value * 1
}
// console.log(person)
this.props.addPeople(person)
}
render() {
return (
<div>
<h1>Person组件,上方组件求和为:{
this.props.sum} </h1>
<input type="text" placeholder='请输入姓名' ref={
c => this.nameNode = c} />
<input type="text" placeholder='请输入年龄' ref={
c => this.ageNode = c} />
<button onClick={
this.addPerson}>添加</button>
<h2>人员列表</h2>
<ul>
{
this.props.peoList.map((p)=>{
return <li key={
p.id}>{
p.name}--{
p.age}</li>
})
}
</ul>
</div>
)
}
}
export default connect(
state => ({
peoList:state.peoples,sum:state.sum}), // 映射状态
{
addPeople:createAddPersonAction} // 映射操作状态的方法
)(Person)
document:Count/index.jsx
// 引入action
import {
createIncrementAction,
createDecrementAction,
createIncrementAsyncAction
} from '../../redux/actions/count'
// 引入react-redux中的connect用于连接UI组件和容器组件
import {
connect } from 'react-redux'
import React, {
Component } from 'react'
class Count extends Component {
increment = () => {
// 普通加
// 1、获取用户选择的值
const {
value } = this.selectNumber
this.props.jia(value*1)
}
decrement = () => {
// 普通减
// 1、获取用户选择的值
const {
value } = this.selectNumber
this.props.jian(value*1)
}
incrementIfOdd = () => {
// 当前求和为奇数为
// 1、获取用户选择的值
const {
value } = this.selectNumber
if (this.props.count %2 !== 0) {
this.props.jia(value*1)
}
}
incrementAsync = () => {
// 异步加
// 1、获取用户选择的值
const {
value } = this.selectNumber
this.props.jiaAsync(value*1,500)
}
render() {
return (
<div>
<h1>当前求和为:{
this.props.count},下方组件人数为{
this.props.peoLens}</h1>
<select ref={
(c) => (this.selectNumber = c)}>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
<button onClick={
this.increment}>+</button>
<button onClick={
this.decrement}>-</button>
<button onClick={
this.incrementIfOdd}>当前求和为奇数为</button>
<button onClick={
this.incrementAsync}>异步加</button>
</div>
)
}
}
// 创建并暴露一个容器组件
export default connect(
state => ({
count: state.sum, peoLens: state.peoples.length}),
{
jia:createIncrementAction,
jian:createDecrementAction,
jiaAsync:createIncrementAsyncAction
}
)(Count)
overall effect:
Summarize
(1). Define a Person
component and share data with the Count
component throughredux
(2). >Regular amountPerson
reducer
action
constant
(3). Key points: Person
’s reducer
and Count
’s Reducer
To use combineReducer
for merging, the total state after merging is an object!
(4). What is handed over tostore
is the totalreducer
. Finally, pay attention to the corresponding status when the component is taken out. key
and value
should be "taken in place".