Reast+Redux+Redux Toolkit+React Persist

原文链接:Redux+React

Redux

一、快速入门

Redux 是一个用于管理 JavaScript 应用程序状态的开源库。它广泛用于 React 应用程序中,但也可以与其他 JavaScript 框架一起使用,如Vue、Angular。Redux 旨在使状态管理更可预测、可维护和可扩展。

安装

npm install redux react-redux
yarn add redux react-redux

在 React 应用中,使用 Redux 通常是在以下场景下有益的:

  1. 共享状态:如果多个组件需要访问相同的状态数据,Redux 可以将这些状态中心化,以便在整个应用程序中共享和更新状态。
  2. 跨组件通信:当你需要在不同的组件之间传递数据或触发动作,Redux 提供了一种统一的方式来实现跨组件通信,而不需要通过多层嵌套传递 props。
  3. 持久化数据:如果你需要在应用程序刷新或导航时保留应用状态,Redux 可以与持久化库(如 Redux Persist)一起使用,以便在本地存储中保存状态数据。
  4. 中间件支持:Redux 支持中间件,这意味着你可以在处理动作时执行额外的逻辑,例如异步数据获取、日志记录、路由导航等。

Redux原理图

image-20231031205433415**

二、使用步骤

步骤 1: 安装 Redux

首先,你需要安装Redux和React-Redux。可以使用npm或者yarn:

# 使用 npm
npm install redux react-redux

# 使用 yarn
yarn add redux react-redux

步骤 2: 创建 Redux Store

在应用的主文件(index.js)中创建Redux store。Redux store是整个应用状态的容器。

// index.js

import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { createStore } from 'redux';
import rootReducer from './redux/reducers'; // 你的根 reducer

import App from './App';

const store = createStore(rootReducer); // 创建 store

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
);

步骤 3: 创建 Reducers

Reducers 定义了应用状态的修改方式。每个 reducer 函数都接收先前的状态和一个 action,返回新的状态。

// src/redux/reducers.js

import { combineReducers } from 'redux';
import countReducer from './countReducer'; // 你的 reducer

const rootReducer = combineReducers({
  count: countReducer, // 将所有的 reducer 放在这里
});

export default rootReducer;

步骤 4: 创建 Action Creators

Action creators 是用来创建 action 的函数。Action 是一个带有type属性的普通 JavaScript 对象,它描述了发生了什么。

// src/redux/actions.js

export const increment = (data) => ({ type:'INCREMENT' , data })

export const decrement = (data) => ({ type:'DECREMENT' , data })

步骤 5: 创建 Reducer 函数

Reducer 函数根据接收到的 action 的类型来更新应用的状态。

// countReducer.js

const countReducer = (preState = 0, action) => {
  const { type , data } = action
  switch (type ) {
    case 'INCREMENT':
      return preState + data;
    case 'DECREMENT':
      return preState - data;
    default:
      return state;
  }
};

export default countReducer;

步骤 6: 在 React 组件中使用 Redux

在 React 组件中,你可以使用connect函数连接组件与 Redux store。

// CountComponent

import React from 'react';
import {connect} from 'react-redux';
import {increment, decrement} from '../../redux/actions'; // 引入 action creators

const CountComponent = ({count, increment, decrement}) => {
    return (
        <div>
            <h1>Count: {count}</h1>
            <button onClick={() => increment(10)}>Increment</button>
            <button onClick={() => decrement(5)}>Decrement</button>
        </div>
    );
};

const mapStateToProps = (state) => {
    return {
        count: state.count, // 这里的 example 对应 rootReducer 中的 key
    };
};

export default connect(mapStateToProps, {increment, decrement})(CountComponent);

步骤 7: 在 React 类式组件中使用 Redux

import React, {Component} from 'react';
import {connect} from 'react-redux';
import {increment, decrement} from '../redux/actions';

class Count extends Component {
    render() {
        return (
            <div>
                <h1>Count: {this.props.count}</h1>
                <button onClick={this.props.increment}>Increment</button>
                <button onClick={this.props.decrement}>Decrement</button>
            </div>
        );
    }
}

const mapStateToProps = (state) => {
    return {
        count: state.count, // 这里的example对应rootReducer中的key
    };
};

export default connect(mapStateToProps, {increment, decrement})(Count);

三、异步Action

在React中使用Redux实现异步操作通常需要使用中间件,最常见的中间件是redux-thunkredux-thunk允许你在Redux action creators中返回函数而不仅仅是普通的action对象,这个函数可以进行异步操作。以下是在React中使用Redux实现异步操作的一般步骤:

步骤 1: 安装redux-thunk

首先,你需要安装redux-thunk中间件。

# 使用 npm
npm install redux-thunk

# 使用 yarn
yarn add redux-thunk

步骤 2: 配置Redux Store

在创建Redux store时,需要将redux-thunk中间件添加到store中。通常,你会在创建store的文件中配置中间件。

import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import {Provider} from 'react-redux';
import {createStore, applyMiddleware} from 'redux';
import thunk from 'redux-thunk';
import rootReducer from './redux/reducers'; // 你的根 reducer

const store = createStore(rootReducer, applyMiddleware(thunk)); // 创建 store

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
    <Provider store={store}>
        <App/>
    </Provider>
);

步骤 3: 创建异步Action Creators

现在,你可以创建异步action creators。这些action creators返回一个函数,而不是一个简单的action对象。这个函数接收dispatch参数,允许你手动分派action。

// actions.js

import {INCREMENT, DECREMENT, ASYNC_DECREMENT} from "./action-type-const";

export const increment = data => ({type: INCREMENT, data})
export const decrement = data => ({type: DECREMENT, data})

// 分发已经定义好的 Action
export const asyncIncrement = (data, time) => {
    return (dispatch) => {
        setTimeout(() => {
            dispatch(increment(data))
        }, time)
    }
}

// 自定义分发 Action
export const asyncDecrement = (data, time) => {
    return (dispatch) => {
        setTimeout(() => {
            dispatch({type: ASYNC_DECREMENT, data})
        }, time)
    }
}

步骤 4: 创建Reducer

import {INCREMENT, DECREMENT, ASYNC_DECREMENT} from "./action-type-const";

const initState = 0

const countReducer = (preState = initState, action) => {
    const {data, type} = action
    switch (type) {
        case INCREMENT:
            return preState + data
        case DECREMENT:
            return preState - data
        case ASYNC_DECREMENT:
            return preState - data
        default:
            return preState
    }
}

export default countReducer

步骤 5: 使用异步Action Creators

在React组件中,你可以使用异步action creators来触发异步操作。这些action creators会分派一系列action来表示操作的不同阶段(例如请求开始、成功或失败)。

import {Component} from "react";
import {connect} from "react-redux";
import {increment, decrement, asyncIncrement, asyncDecrement} from "../../redux/actions";

class Count extends Component {
    render() {
        return (
            <div>
                <h1>当前count:{this.props.count}</h1>
                <button onClick={() => this.props.increment(100)}>+100</button>
                <br/>
                <button onClick={() => this.props.decrement(59)}>-59</button>
                <br/>
                <button onClick={() => this.props.asyncIncrement(39, 2000)}>异步+39</button>
                <br/>
                <button onClick={() => this.props.asyncDecrement(75, 1000)}>异步-75</button>
                <br/>
            </div>
        )
    }
}

export default connect((state) => ({
    count: state.count
}), {increment, decrement, asyncIncrement, asyncDecrement})(Count)

四、Redux Toolkit

Redux Toolkit 是官方推荐的编写 Redux 逻辑的方法。它围绕 Redux 核心,并包含对于构建 Redux 应用必不可少的软件包和功能。Redux Toolkit ,简化了大多数 Redux 任务,防止了常见错误,并使编写 Redux 应用程序更加容易。

步骤 1:安装 Redux Toolkit

# NPM
npm install @reduxjs/toolkit react-redux

# Yarn
yarn add @reduxjs/toolkit react-redux

步骤 2: 创建Toolkit的Slice

在Redux Toolkit中,状态管理通过Slice来定义。一个Slice包括了状态的初始值、Reducer函数以及可以自动处理的Action创建函数。action.payload 是 Redux 中的一个约定,它通常用来传递操作(action)所需的数据。在 Redux Toolkit 中,action.payload 是一个操作的有效负载,用于在 reducer 中更新状态。

创建一个Slice。例如,counterSlice.js

import {createSlice} from "@reduxjs/toolkit";

const countSlice = createSlice({
    name: 'count',
    initialState: {
        count: 0
    },
    reducers: {
        increment: (state, action) => {
            state.count += action.payload;
        },
        decrement: (state, action) => {
            state.count -= action.payload;
        },
    }
})

export const {increment, decrement} = countSlice.actions;
export default countSlice.reducer;

步骤 3:配置Redux Store

在应用中创建Redux Store,将Slice的Reducer添加到Store中。例如,store.js

// store.js
import {configureStore} from "@reduxjs/toolkit";
import countReducer from './count'

const store = configureStore({
    reducer: {
        count: countReducer
    }
})

export default store

步骤 4:提供Redux Store到应用

在React应用的顶层组件index.js,使用`组件提供Redux Store:

import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import {Provider} from 'react-redux'
import store from "./store/store";

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
    <Provider store={store}>
        <React.StrictMode>
            <App/>
        </React.StrictMode>
    </Provider>
);

步骤 5:在组件中使用Redux状态

在React组件中,可以使用useSelector来选择Redux状态,以及useDispatch来分发Redux动作。例如:

import React from 'react';
import {useSelector, useDispatch} from 'react-redux';
import {increment, decrement} from '../store/count';

function Counter() {
    const count = useSelector((state) => state.count.count);
    const dispatch = useDispatch();

    return (
        <div>
            <p>Counter: {count}</p>
            <button onClick={() => dispatch(increment(1))}>Increment</button>
            <button onClick={() => dispatch(decrement(1))}>Decrement</button>
        </div>
    );
}

export default Counter;

步骤 6:在类组件中使用Redux状态

// src/components/Counter.js
import React from 'react';
import {connect} from 'react-redux';
import {increment, decrement} from '../store/count';

class Counter2 extends React.Component {
    render() {
        return (
            <div>
                <p>Count: {this.props.count}</p>
                <button onClick={() => this.props.increment(5)}>+5</button>
                <button onClick={() => this.props.decrement(5)}>-5</button>
            </div>
        );
    }
}

const mapStateToProps = (state) => ({
    count: state.count.count,
});

const mapDispatchToProps = {increment, decrement};

export default connect(mapStateToProps, mapDispatchToProps)(Counter2);

五、Redux Toolkit异步操作

步骤 1:设置 Redux Store

Redux Toolkit 简化了 Redux 在 React 应用中的使用,包括异步操作的处理。Redux Toolkit 提供了 createAsyncThunk 函数来轻松地处理异步操作,它接受两个参数:

  1. typePrefix(字符串):typePrefix 是一个用于创建 action type 的前缀字符串,通常以描述 action 的方式命名。Redux Toolkit 会自动为你生成三个 action types,分别对应于异步操作的不同状态:typePrefix/pendingtypePrefix/fulfilledtypePrefix/rejected
  2. payloadCreator(函数):payloadCreator 是一个异步函数,它包含了实际的异步操作逻辑,例如从服务器获取数据。payloadCreator 函数会在异步 action 被调用时执行,并且返回一个 Promise。当 Promise 被解决时,Redux Toolkit 会根据解决的值生成一个包含 payload 属性的 action。这个 payload 属性包含了异步操作的结果数据,通常是一个对象或数组。
import {createAsyncThunk, createSlice} from "@reduxjs/toolkit";

// 创建一个异步 thunk action
export const asyncIncrement = createAsyncThunk("async/increment", async () => {
    const response = await fetch('/api/todos');
    return await response.json();
})

const countSlice = createSlice({
    name: 'count',
    initialState: {
        count: 0
    },
    reducers: {
        increment: (state, action) => {
            state.count += action.payload;
        },
        decrement: (state, action) => {
            state.count -= action.payload;
        },
    },
    extraReducers: (builder) => {
        builder
            .addCase(asyncIncrement.pending, (state) => {
                console.log("asyncIncrement 正在执行中")
            })
            .addCase(asyncIncrement.fulfilled, (state, action) => {
                console.log(action)
            })
            .addCase(asyncIncrement.rejected, (state, action) => {
                console.log("asyncIncrement 出错了")
            })
    }
})

export const {increment, decrement} = countSlice.actions;
export default countSlice.reducer;

步骤 2:使用Redux Store

import React from 'react';
import {useSelector, useDispatch} from 'react-redux';
import {increment, decrement, asyncIncrement} from '../store/count';

function Counter() {
    const count = useSelector((state) => state.count.count);
    const dispatch = useDispatch();

    return (
        <div>
            <p>Counter: {count}</p>
            <button onClick={() => dispatch(increment(1))}>Increment</button>
            <button onClick={() => dispatch(decrement(1))}>Decrement</button>
            <button onClick={() => dispatch(asyncIncrement(1))}>异步+1</button>
        </div>
    );
}

export default Counter;

六、Redux Persist数据持久化

Redux Toolkit 是一个用于简化 Redux 开发的工具集,而 Redux Persist 是一个用于在 Redux 中实现数据持久化的库。当你想要将它们与 React 一起使用时,可以按照以下步骤进行配置:

步骤1:安装必要的库

# 使用 npm
npm install @reduxjs/toolkit react-redux redux-persist

# 使用 yarn
yarn add @reduxjs/toolkit react-redux redux-persist

步骤2:创建CounterSlice和UserSlice

import {createSlice} from "@reduxjs/toolkit";

const counterSlice = createSlice({
  name: 'count',
  initialState: {
    count: 0
  },
  reducers: {
    increment: (state, action) => {
      state.count += action.payload
    },
    decrement: (state, action) => {
      state.count -= action.payload
    }
  }
})

export const {increment, decrement} = counterSlice.actions
export default counterSlice.reducer

// userSlice
import {createSlice} from "@reduxjs/toolkit";

const userSlicer = createSlice({
  name: 'user',
  initialState: {
    name: 'jvyou'
  },
  reducers: {
    update: (state) => {
      state.name += '@'
    }
  }
})

export const {update} = userSlicer.actions
export default userSlicer.reducer

步骤3:组合所有的Reducer

使用combineReducers将所有的reducer组合在一起,创建store/rootReducers

import {combineReducers} from "redux";
import CounterReducer from '@/store/CounterSlice.ts'
import UserReducer from "@/store/UserSlicer.ts";
// 指定类型,方便代码提示
const rootReducer = combineReducers<{count,user}>({
  count: CounterReducer,
  user: UserReducer
})

export default rootReducer

步骤3:创建 Redux store

使用 Redux Toolkit 的 configureStore 函数来创建 Redux store。在创建 store 的同时,配置 Redux Persist 的 persistReducer

import {configureStore} from "@reduxjs/toolkit";
import rootReducer from "@/store/RootReducer.ts";
import {persistReducer, persistStore} from 'redux-persist';
import storage from 'redux-persist/lib/storage';


const persistConfig = {
  key: 'root',
  storage,
  whitelist: ['count'], // 只持久化 CounterReducer
};

const persistedReducer = persistReducer(persistConfig, rootReducer);

// 将所有的 Reducer 交给 persistedReducer 管理
export const store = configureStore({
  reducer: {
    pr: persistedReducer
  },

  // 其他配置项
  middleware: getDefaultMiddleware => getDefaultMiddleware({
    //关闭redux序列化检测
    serializableCheck: false
  })
});

export const persistor = persistStore(store);

export type StateType = ReturnType<typeof store.getState>;

上述代码中,persistConfig 是 Redux Persist 的配置,用于指定持久化的关键信息和存储引擎。persistReducer 将根 reducer 包装起来,以便在其中应用持久化。

步骤4:在应用中使用 Redux Provider

在应用的顶层组件中使用 Redux Provider,并传入上一步创建的 store

// src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { PersistGate } from 'redux-persist/integration/react';

import App from './App';
import { store, persistor } from './app/store';

ReactDOM.render(
  <Provider store={store}>
    <PersistGate loading={null} persistor={persistor}>
      <App />
    </PersistGate>
  </Provider>,
  document.getElementById('root')
);

PersistGate 用于在加载过程中显示加载状态,直到持久化完成。

步骤5:组件使用 Redux

在 React 组件中使用 react-redux 提供的 useSelectoruseDispatch 钩子,就像在普通的 Redux 应用中一样,刷新之后,count值不变,user的name被重置。

import React from 'react';
import {Button} from "antd";
import {decrement, increment} from "@/store/CounterSlice.ts";
import {useDispatch, useSelector} from "react-redux";
import {StateType} from "@/store";
import {update} from "@/store/UserSlicer.ts";


const Home: React.FC = () => {
  const count = useSelector((state: StateType) => state.pr.count.count)
  const user = useSelector((state: StateType) => state.pr.user)

  const dispatch = useDispatch();

  return (
    <div>
      <h1>Home</h1>
      <h1>{count}</h1>
      <Button onClick={() => dispatch(increment(100))}>+100</Button>
      <Button onClick={() => dispatch(decrement(100))}>-100</Button>
      <hr/>
      {user.name}
      <Button onClick={() => dispatch(update())}>更新姓名</Button>
    </div>
  );
};

export default Home;

通过以上步骤,你就配置好了 Redux Toolkit、React 和 Redux Persist 的集成,实现了数据的持久化。确保你的 reducer 和持久化的配置是正确的,以便在应用启动时从存储中恢复状态。

七、Redux开发者工具

Redux开发者工具的使用步骤如下:

在Chrome安装 Redux 开发者工具

安装依赖:

npm i redux-devtools-extension

yarn add redux-devtools-extension

在 store 中引入 devtools:

import {createStore, applyMiddleware} from "redux";
import thunk from "redux-thunk";
import rootReducer from "./redux/reducers";
import {composeWithDevTools} from 'redux-devtools-extension'


const store = createStore(rootReducer, composeWithDevTools(applyMiddleware(thunk)))
  • 11
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值