核心思想:单一数据源、状态是只读的、以及使用纯函数更新状态。
组成部分
Store(存储)
应用的唯一状态容器,存储整个应用的状态树,使用 createStore()
创建。
getState()
:获取当前状态。dispatch(action)
:派发动作以触发状态更新。subscribe(listener)
:订阅状态变化。
Action(动作)
描述应用中发生的事情,就是一个普通的 JavaScript 对象,必须有 type
属性,用来描述动作的类型,其他字段可以包含任何附加信息(例如,payload)。
Reducer(状态处理器)
是一个纯函数,接收当前的状态和一个动作,返回新的状态,函数签名:(state, action) => newState,
通过处理不同类型的动作更新状态。
Middleware(中间件)
拦截 dispatch
的动作,用于扩展 Redux 的功能,例如处理异步操作(redux-thunk
)或日志记录(redux-logger
)。
Provider(React 集成部分)
使用 react-redux
提供 Provider
组件,将 Redux 的 store 传递给整个 React 组件树。
应用
安装依赖
npm install redux react-redux
创建 Redux Store
定义Action
// src/actions/types.js
// 定义一些常量来表示 action 的类型,这有助于避免拼写错误
export const INCREMENT = "INCREMENT";
export const DECREMENT = "DECREMENT";
// src/actions/counterActions.js
// 创建 action creator 函数来生成 action 对象。
import { INCREMENT, DECREMENT } from "./types";
export const increment = () => ({
type: INCREMENT,
});
export const decrement = () => ({
type: DECREMENT,
});
创建 Reducer
// src/reducers/counterReducer.js
// 创建 reducer 函数来处理不同的 action 类型。
import { INCREMENT, DECREMENT } from "../actions/types";
const initialState = {
count: 0,
};
function counterReducer(state = initialState, action) {
switch (action.type) {
case INCREMENT:
return {
...state,
count: state.count + 1,
};
case DECREMENT:
return {
...state,
count: state.count - 1,
};
default:
return state;
}
}
export default counterReducer;
// src/reducers/index.js
import { combineReducers } from "redux";
import counterReducer from "./counterReducer";
const rootReducer = combineReducers({
counter: counterReducer,
});
export default rootReducer;
创建 Store
// store.js
import { createStore } from 'redux';
import counterReducer from './reducer';
const store = createStore(counterReducer);
export default store;
在 React 应用中使用 Redux
设置 Provider
// index.js
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
// Provider是React-Redux提供的一个组件,用于将Redux store传递给应用中的所有组件。
import { Provider } from "react-redux";
import store from "./store/index";
import reportWebVitals from "./reportWebVitals";
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<React.StrictMode>
<Provider store={store}>
{" "}
{/* 将App组件包裹在Provider中 */}
<App />
</Provider>
</React.StrictMode>
);
reportWebVitals();
组件中访问状态和派发动作
// src/components/js/CounterWithHooks.js
import React from "react";
import { useSelector, useDispatch } from "react-redux";
import { increment, decrement } from "../../actions/counterActions";
function CounterWithHooks() {
const count = useSelector((state) => state.counter.count);
const dispatch = useDispatch();
return (
<div>
<h1>Count: {count}</h1>
<button onClick={() => dispatch(increment())}>Increment</button>
<button onClick={() => dispatch(decrement())}>Decrement</button>
</div>
);
}
export default CounterWithHooks;
Redux 中间件的扩展
添加异步支持(redux-thunk
)
npm install redux-thunk
修改 store.js
import { createStore, applyMiddleware } from 'redux';
import {thunk} from 'redux-thunk';// 使用命名导出
// import thunk from 'redux-thunk';// 使用默认导出
import counterReducer from './reducer';
const store = createStore(counterReducer, applyMiddleware(thunk));
export default store;
示例异步 Action
// src/actions/counterActions.js
// 创建 action creator 函数来生成 action 对象。
import { INCREMENT, DECREMENT } from "./types";
export const increment = () => ({
type: INCREMENT,
});
export const decrement = () => ({
type: DECREMENT,
});
export const incrementAsync = () => {
return (dispatch) => {
setTimeout(() => {
dispatch(increment());
}, 1000);
};
};
export const decrementAsync = () => {
return (dispatch) => {
setTimeout(() => {
dispatch(decrement());
}, 1000);
};
};
示例
// src/components/js/CounterWithHooks.js
import React from "react";
import { useSelector, useDispatch } from "react-redux";
import { increment, decrement, incrementAsync, decrementAsync } from "../../actions/counterActions";
function CounterWithHooks() {
const count = useSelector((state) => state.counter.count);
const dispatch = useDispatch();
return (
<div>
<h1>Count: {count}</h1>
<button onClick={() => dispatch(increment())}>Increment</button>
<button onClick={() => dispatch(decrement())}>Decrement</button>
<button onClick={() => dispatch(incrementAsync())}>Increment Async</button>
<button onClick={() => dispatch(decrementAsync())}>Decrement Async</button>
</div>
);
}
export default CounterWithHooks;
总结
- State: 整个应用的状态树。
- Actions: 描述状态变化的对象。
- Reducers: 纯函数,根据 action 更新 state。
- Store: 持有应用的 state 树,提供方法来获取 state、分发 action 和注册/注销监听器。