React-Redux详解

一、‌核心概念与作用

1‌.定义

‌React-Redux 是 Redux 的官方 React 绑定库,用于在 React 应用中实现状态集中管理,通过 Store 统一维护全局状态,并通过 Action 和 Reducer 实现状态的更新与同步。

1‌.核心组件

  • Store‌:存储应用全局状态的唯一容器,通过 createStore 创建。
  • Action‌:描述状态变化的纯对象,必须包含 type 字段,如 { type: 'CLOSE_LOADING', data: false }
  • Reducer‌:纯函数,接收旧状态和 Action,返回新状态,如 (state, action) => newState
  • Dispatch‌:唯一修改状态的途径,通过 dispatch(action) 触发 Reducer。
  • Selector‌:用于从 Store 中提取特定状态,如 useSelector 钩子。

二、‌工作原理与数据流

‌1.单向数据流

  • 触发‌:组件通过 dispatch(action) 发起状态变更请求。
  • 处理‌:Reducer 根据 Action 类型生成新状态。
  • 更新‌:Store 更新后,通知所有订阅状态的组件重新渲染。

‌2.三大原则

  • 单一数据源‌:整个应用状态仅存于一个 Store 中。
  • 状态只读‌:只能通过 Dispatch Action 修改状态。
  • 纯函数 Reducer‌:确保状态变更可预测且无副作用。

三.基本使用 

 1.在src目录下创建redux文件夹,并创建action,reducer,store三个文件夹 

2.创建 Store 和 Reducer

 ‌ 1.使用 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;
 2.编写reducer
//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
            }
    }
}
3.编写action

组件中调用 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
});

 3.在react组件中引入

1.类组件 

 首先,在 在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 ;
}

 四.高级用法

1.中间件

在 Action 被 Dispatch 到 Reducer 之前拦截处理,实现异步操作、日志记录、异常监控等功能 

本质是增强 dispatch() 方法,支持处理非普通对象类型的 Action(如函数、Promise)

  1. redux-thunk 实现异步 Action

    • 通过中间件允许 Action Creator 返回函数而非普通对象,实现延迟执行或条件触发 
//初始化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 处理复杂副作用

  • 使用 Generator 函数管理异步流程,支持更细粒度的控制(如取消任务、并发处理)

Action 的完整处理流程为:
Dispatch → Saga 中间件 → Reducer(或其他中间件)

  • 若 Action 未被 Saga 监听,直接流向后续中间件或 Reducer 
  • 若 Action 被 Saga 捕获,则执行对应 Worker Saga 后再决定是否继续传递 Action  
方法 作用 示例场景
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‌,只有通过 taketakeEverytakeLatest 等 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

 2.combineReducers 拆分逻辑

  • 将全局 Reducer 拆分为多个子 Reducer,提升可维护性
import { combineReducers } from 'redux';
const rootReducer = combineReducers({
  user: userReducer,
  posts: postsReducer
});

 3.redux-persist状态持久化

  • 将 Store 状态持久化到 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);

4‌.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 不变

你可能感兴趣的:(react.js,javascript,前端)