React-Redux 是 Redux 的官方 React 绑定库,用于在 React 应用中实现状态集中管理,通过 Store 统一维护全局状态,并通过 Action 和 Reducer 实现状态的更新与同步。
createStore
创建。type
字段,如 { type: 'CLOSE_LOADING', data: false }
。(state, action) => newState
。dispatch(action)
触发 Reducer。useSelector
钩子。dispatch(action)
发起状态变更请求。createStore
创建全局 Store// store/index.js
import { createStore, applyMiddleware } from 'redux';
import reducer from '../reducer';
import thunk from 'redux-thunk';
const store = createStore(reducer, applyMiddleware(thunk));
export default store;
//reducer/index.js
import * as type from '../../action/type';
const _state = { isLoading: false }
export default (state = _state, action) => {
switch (action.type) {
case type.OPEN_LOADING:
return {
...state,
isLoading: action.data,
}
case type.CLOSE_LOADING:
return {
...state,
isLoading: action.data,
}
}
default :
return {
...state
}
}
}
组件中调用 Action 时必须显式导入对应的 Action Creator(即生成 Action 对象的函数)
// actions/index.js
export const INCREMENT = 'INCREMENT';
export const DECREMENT = 'DECREMENT';
export const increment = (value) => ({
type: INCREMENT,
payload: value
});
export const decrement = (value) => ({
type: DECREMENT,
payload: value
});
首先,在 在index.js组件中通过provide组件注入store
import { Provider } from 'react-redux';
import store from './redux/store';
ReactDOM.render(
,
document.getElementById('root')
);
你需要从react-redux
中导入connect
函数。然后,你可以使用connect
来创建一个容器组件,这个组件会将Redux store的状态作为props传递给你的类组件。
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { increment, decrement } from '../actions/counter';
class MyComponent extends Component {
render() {
const { someStateFromRedux,addPerson } = this.props;
return {someStateFromRedux};
}
}
// 定义mapStateToProps函数,它将Redux state映射到props上
const mapStateToProps = (state) => ({
someStateFromRedux: state.someReducer.someState
});
function mapDispathToProps(dispath) {
return {
addPerson:(data)=>{dispath(increment(data))}
}
}
// 使用connect函数连接Redux和你的组件
export default connect(mapStateToProps,mapDispathToProps)(MyComponent);
2.在函数组件中
使用useSelector
获取Redux状态。useSelector
Hook允许你从Redux store中提取数据。它接收一个函数作为参数,这个函数接收整个store的状态,并返回需要的数据。
//在这个例子中,someReducer.data是从Redux store中提取的数据。你需要确保你的store配置了相应的reducer,并且该reducer的state中包含了
import React from 'react';
import { useSelector } from 'react-redux';
function MyComponent() {
const myData = useSelector(state => state.someReducer.data);
return {myData};
}
使用useDispatch
分发actions,useDispatch
Hook返回一个引用(reference),你可以使用它来分发actions。这对于触发reducer中的逻辑来更新store的状态非常有用。
import React from 'react';
import { useDispatch } from 'react-redux';
import { someAction } from './actions'; // 确保引入了相应的action creator
function MyComponent() {
const dispatch = useDispatch();
const handleClick = () => {
dispatch(someAction()); // 分发action来更新store
};
return ;
}
在 Action 被 Dispatch 到 Reducer 之前拦截处理,实现异步操作、日志记录、异常监控等功能
本质是增强 dispatch()
方法,支持处理非普通对象类型的 Action(如函数、Promise)
redux-thunk
实现异步 Action
//初始化redux-thunk
// store/index.js
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import rootReducer from './reducers';
const store = createStore(rootReducer, applyMiddleware(thunk));
//编写异步action
// actions/data.js
export const fetchDataSuccess = (data) => ({
type: 'FETCH_DATA_SUCCESS',
payload: data
});
export const fetchData = () => (dispatch) => {
fetch('/api/data')
.then(res => res.json())
.then(data => dispatch(fetchDataSuccess(data)));
};
import React, {Component} from "react";
import { connect } from 'react-redux';
import {fetchData } from "../../action/index.js";
class BasicLayout extends Component{
constructor(props){
super(props)
}
componentDidMount(){
this.props.getGlobalInfo()
}
render(){
return (
dispatch
)
}
}
function mapDispathToProps(dispath) {
return {
getGlobalInfo:()=>{dispath(fetchData ())}
}
}
export default connect(state=>state,mapDispathToProps)(BasicLayout)
2.redux-saga
处理复杂副作用
Action 的完整处理流程为:
Dispatch → Saga 中间件 → Reducer(或其他中间件)
方法 | 作用 | 示例场景 |
---|---|---|
call |
调用异步函数(如 API 请求),支持 Promise 和同步函数 | yield call(api.fetchUser, id) |
put |
触发 Action(相当于 dispatch ) |
yield put({ type: 'SUCCESS' }) |
takeEvery |
监听所有指定 Action,并发执行 Worker Saga | 处理多次点击事件 |
takeLatest |
监听指定 Action,取消之前未完成的 Saga,仅执行最后一次 | 搜索框输入防抖 |
all |
并行执行多个 Saga,类似 Promise.all |
合并多个子 Saga |
// store.js
import createSagaMiddleware from 'redux-saga';
import rootSaga from './sagas';
const sagaMiddleware = createSagaMiddleware();
const store = createStore(rootReducer, applyMiddleware(sagaMiddleware));
//sagaMiddleware.run(rootSaga) 将主 Saga 与 Redux Store 绑定,启动全局监听
sagaMiddleware.run(rootSaga);
Redux-Saga 不会处理所有被 dispatch
的 Action,只有通过 take
、takeEvery
、takeLatest
等 Effect 显式监听 的 Action 才会触发 Saga 逻辑
// sagas/index.js
import { all } from 'redux-saga/effects';
import { watchLogin, watchFetchData } from './featureSagas';
export default function* rootSaga() {
yield all([watchLogin(), watchFetchData()]); // 并行启动多个监听 Saga all的作用是将所有的saga函数进行聚合,统一地进行监听
}
主sgaa->监听saga->workersaga
//featureSagas/index.js 里面都是被监听的workerSaga
// sagas/index.js
// sagas/featureSagas.js
import { takeEvery, put, call } from 'redux-saga/effects';
import { FETCH_DATA_REQUEST, fetchDataSuccess } from '../actions';
//执行具体副作用操作(如 API 调用、缓存操作),并通过 put 触发状态更新
function* fetchDataWorker(action) {
try {
//发异步请求 call函数发异步请求,阻塞式的调用
// put函数发出新的action,非阻塞式的执行
const data = yield call(api.fetchData, action.payload);
yield put(fetchDataSuccess(data));
} catch (error) {
yield put({ type: 'FETCH_DATA_FAILED', error });
}
}
//Action 监听:使用 takeEvery、takeLatest 或 take 监听特定 Action 类型,触发 Worker Saga
//监听FETCH_DATA_REQUEST
export function* watchFetchData() {
// //takeEvery接受两个参数: 第一个是组件传来的action 第二个参数是向reducer传递的action
yield takeEvery("FETCH_DATA_REQUEST", fetchDataWorker);
}
//主组件中触发action
dispatch({ type: 'FETCH_DATA_REQUEST', payload: { username: 'admin', password: 'admin888' } })
const initState = {
uid: 0,
token: '',
nickname: ''
}
const reducer = (state = initState, { type, payload }) => {
// reducer函数处理 userlogin 类型的 action
if ('FETCH_DATA_FAILED' === type) return { ...state, ...payload }
return state
}
export default reducer
combineReducers
拆分逻辑import { combineReducers } from 'redux';
const rootReducer = combineReducers({
user: userReducer,
posts: postsReducer
});
redux-persist
状态持久化localStorage
或 AsyncStorage
,实现页面刷新后状态恢复import { persistStore, persistReducer } from 'redux-persist';
import storage from 'redux-persist/lib/storage';
const persistConfig = { key: 'root', storage };
const persistedReducer = persistReducer(persistConfig, rootReducer);
const persistor = persistStore(store);
Immutable.js
优化状态更新使用不可变数据结构提升状态变更效率,减少深拷贝开销。
Immutable.js 是 Facebook 团队开发的一个 JavaScript 库,专注于创建不可变数据结构(Immutable Data Structures)。
不可变性:所有数据一旦创建便无法直接修改,任何变更操作都会生成新的数据副本,原始数据保持不变。
持久化数据结构:通过复用未修改部分的数据结构,减少内存占用并提升性能
import { Map } from 'immutable';
const initialState = Map({ count: 0 });
const reducer = (state = initialState, action) => {
return state.set('count', action.payload);
};
const list1 = Immutable.List([1, 2, 3]);
const list2 = list1.push(4); // 生成新对象,原 list1 不变