【青训营】- React Redux 状态管理层√

555 阅读4分钟

📄目录结构

  • Redux是什么?
  • 什么时候用Redux?
  • 如何使用react-redux?
  • Redux术语
  • 如何使用redux toolkit?

🔖Demo

标题Demo
react-reduxDemo
redux toolkitDemo

Redux是什么?

它是状态管理层的解决方案,状态是什么?简单来说就是react当中的state。随着逻辑越来越复杂,我们就需要去引入专门的一层来去做状态管理相关的事情,redux就是这样的一层。

我们先来看一个简单的计数器组件:

function Counter() {
    // State:计数器值
    const [counter, setCounter] = useState(0);
    
    // Action:当发生某一操作时,更新状态
    const increment = () => {
        setCounter(prevCounter => prevCounter + 1)
    }
    
    // View: UI定义
    return (
        <div>
            value: {counter}
            <button onClick={increment}>Increment</button>
        </div>
    )
}

这个计数器组件可以分为三个阶段:

第一个阶段是我们在组件里面定义了一个计数器状态;接着我们用这个计数器状态去定义视图层的UI结构、UI内容;当我们点击视图层的按钮,可以触发这个状态的更新,也就是Action。

所以这三个阶段是:

  1. State:计数器值
  2. Action:当发生某一操作时,更新状态。
  3. View:UI定义。

image.png

什么时候用Redux?

只有应用复杂到一定程度的时候,redux才会给我们带来收益,否则只会增加我们整个应用的复杂度。

image.png 这里提到了两个问题:

  1. 假设B2-B3存在共享的状态,那应该怎么做呢?
  2. 那如果B2-A2这两个组件有需要共享的组件应该怎么办呢? 对于问题1,有专门的解决方案,叫做状态提升。就是把B2和B3公用的state提升到B1这个层级。

也就是B1这个组件去管理公用的state,然后B1组件通过props传递给B2、B3,这样B2、B3都可以去使用B1这个state,这其实就是一个状态提升。

对于问题2,我们是按照状态提升的原则,将A1、B2的共有状态提升到A1,然后再由A1经过B1返给B2,这个时候我们通过状态提升去解决状态共享就有一些麻烦了。

当组件树的层级越复杂然后要共享的节点之间离得越远,层级差异度越大,这个通过状态提升解决的问题复杂度也会越高。

这时候通过redux引入一个全局的状态管理,可以让任意层级的组件在需要使用相关状态的时候直接从redux当中去获取就可以了。

避免了需要一层层的组件传递的问题。

如何使用react-redux?

我们以实现一个计算器为例:

image.png

当我们在页面按下“加数”,看到的是0变成2的结果。实际上,内部的过程是通过onClick事件调用方法去执行。

onClick里的addAmount方法会返回action,dispatch把action传给reducer。reducer根据action里的type进行判断并返回计算结果,页面更新state。

这就是在页面上由0增加为2的整个过程。

实现逻辑被我抽象成了下图:

实现逻辑.jpg

作为练手的入门小项目,我的src目录如下,

| -index.js入口文件

| - App.js 入口组件

| - Counter.js 计算器组件

| - store.js 整个项目唯一保存数据的地方,可以当做容器

| - reducer.js 接收action并且帮助store生成state的计算过程

| - actions.js 用户在网页上触发的操作

| - styles.css 样式文件

    // index.js
    import ReactDOM from "react-dom";
    import { Provider } from "react-redux";
    import { store } from "./store";
    const rootElement = document.getElementById("root");
    ReactDOM.render(
        <Provider store={store}>
            <App />
        </Provider>
        ,
        rootElement
    );

在入口就通过Provider提供store,这样即使后面有再多的组件,都可以通过useSelector取到state。

Redux术语

import { configureStore } from '@reduxjs/toolkit'

const store = configureStore({ reducer: counterReducer })

console.log(store.getState())

reduxjs/toolkit就是基于Redux的上层封装库,reduxtoolkit,简称RTK。 通过这个库来使用redux来变得更加简洁。

我们导入RTK库里的configureStore就可以创建出来storeconfigure当中传入的是一个reducer的一个对象。

再通过getState保存的方法,我们就能拿到这个store当中保存的状态。

如何使用redux toolkit?

我们通过增减计数例子来学习:

image.png

目录结构按照官方文档提供的来:

  • app
    • store.js
  • features
    • counter
      • Counter.js
      • counterSlice.js
  • App.js
  • index.js
  • styles.css

特别值得注意的是它比react-redux多了一个叫counterSlice的文件,所以我们重点放在它上面。

// counterSlice.js
import { createSlice } from "@reduxjs/toolkit";
const initialState = {
    value: 0
};

export const counterSlice = createSlice({
    name:"counter",
    initialState,
    reducers: {
        increment: (state) => {
            // Redux Toolkit 允许我们在reducer中编写“变异(mutating)”逻辑。
            // state.value+=1 它实际上并不改变状态,是纯函数。
            // 因为它使用Timmer库,它检测‘draft状态’的变化
            // 并基于这些变化产生一个全新的不可变状态
            state.value += 1;
        },
        decrement: (state) => {
            state.value -= 1;
        },
        incrementByAmount: (state, action) => {
            state.value += action.payload;
        }
    }
});