效果

src 目录结构
.
├── App.js
├── containers # 放置容器组件
│ ├── Count
│ │ └── index.jsx
│ └── Person
│ └── index.jsx
├── index.js
└── redux # 放置 redux 文件
├── actions # 放置 action
│ ├── count.js
│ └── person.js
├── constant.js # 定义 action 的 type
├── reducers # 放置 reducer
│ ├── count.js
│ ├── index.js # reducer 汇总
│ └── person.js
└── store.js # store 文件
代码及注释
App.js
import Count from './containers/Count' // 引入 Count 的容器组件
import Person from './containers/Person' // 引入 Person 的容器组件
function App() {
return (
<div>
<Count />
<hr />
<Person />
</div>
);
}
export default App;
containers/Count/index.jsx
import { Component } from 'react'
// 引入 action
import { increment, incrementAsync } from '../../redux/actions/count'
// 引入 connect 用于连接 UI 组件和 Redux
import { connect } from 'react-redux'
// 定义 UI 组件
class Count extends Component {
render() {
const { count, persons, increment, incrementAsync } = this.props
return (
<div>
<h1>我是 Count 组件</h1>
<h2>我的 count 值:{count},下方 Person 组件的人数:{persons.length}</h2>
<button onClick={() => increment(1)}>同步 +1</button>
<button onClick={() => incrementAsync(1, 1000)}>异步 +1</button>
</div>
)
}
}
// 使用 connect()() 创建并暴露一个容器组件
export default connect(
state => ({
persons: state.persons,
count: state.count
}), // 映射 redux 状态到 UI 组件的属性,redux 状态在汇总的 reducer 中定义
{ increment, incrementAsync } // 映射操作状态的方法
)(Count)
containers/Person/index.jsx
import { Component } from 'react'
import { addPerson } from '../../redux/actions/person'
import { connect } from 'react-redux'
class Person extends Component {
render() {
const { count, persons, addPerson } = this.props
return (
<div>
<h1>我是 Person 组件</h1><h2>上方 Count 组件值为:{count}</h2>
<button onClick={() => addPerson({ id: Math.random(), name: 'tom', age: 18 })}>添加一人</button>
<ul>
{persons.map((person) =>
(<li key={person.id}>名字:{person.name} 年龄:{person.age}</li>)
)}
</ul>
</div>
)
}
}
export default connect(
state => ({ count: state.count, persons: state.persons }),
{ addPerson }
)(Person)
index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import store from './redux/store'
import { Provider } from 'react-redux';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
// 此处用 Provider 包裹 App,让 App 所有的后代容器组件都能接收到 store
<Provider store={store}>
<App />
</Provider>
);
redux/actions/count.js
// 此文件专门为 Count 组件生成 action 对象
import { INCREMENT } from '../constant'
// 同步 action,action 值为一般对象
// count 同步增加
export const increment = data => ({ type: INCREMENT, data: data })
// 异步 action,action 值为函数,在函数内可异步派发同步 action
// count 异步增加
export const incrementAsync = (data, time) => {
return (dispatch) => {
setTimeout(() => {
dispatch(increment(data))
}, time)
}
}
redux/actions/person.js
import { ADD_PERSON } from '../constant'
// 增加一个人的 action 对象
export const addPerson = personObj => ({ type: ADD_PERSON, data: personObj })
redux/constant.js
// 定义 action 中的 type,目的是为了便于管理和防止写错
export const ADD_PERSON = 'add_person'
export const INCREMENT = 'increment'
redux/reducers/count.js
import { INCREMENT } from '../constant'
// 初始化计数
const initState = 0
export default function countReducer(preState = initState, action) {
const { type, data } = action
switch (type) {
case INCREMENT:
return preState + data
default:
// 初始化时传入的 preState 为 undefined,因此会返回 initState,完成初始化
// type 不对时,会返回 preState,状态不变
return preState
}
}
redux/reducers/index.js
// 此文件用于汇总所有的 reducer 为一个 reducer
// 用于汇总多个 reducer
import { combineReducers } from "redux";
// 为 Count 组件服务的 reducer
import count from './count'
// 为 Person 组件服务的 reducer
import persons from './person'
// 汇总
export default combineReducers({
count,
persons
})
redux/reducers/person.js
import { ADD_PERSON } from '../constant'
// 初始化人的列表
const initState = [{ id: '1', name: 'tom', age: 18 }]
export default function personReducer(preState = initState, action) {
const { type, data } = action
switch (type) {
case ADD_PERSON: // 若是添加一个人
// 返回的对象和原对象不是同一个才会触发重新渲染,所以不能返回原对象
return [data, ...preState]
default:
// 初始化时传入的 preState 为 undefined,因此会返回 initState,完成初始化
// type 不对时,会返回 preState,状态不变
return preState
}
}
redux/store.js
// 引入 createStore 用于创建 store 对象,引入 applyMiddleware 用于添加异步功能
import { createStore, applyMiddleware } from 'redux'
// 引入汇总后的 reducer
import reducer from './reducers'
// 用于支持异步 action
import thunk from 'redux-thunk'
// 用于配合浏览器插件调试 redux
import { composeWithDevTools } from 'redux-devtools-extension'
// 创建并暴露 store
export default createStore(reducer, composeWithDevTools(applyMiddleware(thunk)))