likes
comments
collection
share

Redux了解、安装及简单使用

作者站长头像
站长
· 阅读数 16

redux是公共状态管理方案 官网

概念

store

下面是store打印结果:

Redux了解、安装及简单使用

store内的方法

具体详细的store方法可以看官网

dispatch

更新 state 的唯一方法是调用 store.dispatch() 并传入一个 action 对象

getState

store 将执行所有 reducer 函数并计算出更新后的 state,调用 getState() 可以获取新 state。

let { count } = store.getState()

subscribe

每当 dispatch action 的时候就会执行,state 树中的一部分可能已经变化。你可以在回调函数里调用 getState() 来拿到当前 state。

store.subscribe(() => {
    console.log("subscribe", store.getState())
})

action

将 action 视为描述应用程序中发生了什么的事件. type: 字符串,给这个 action 一个描述性的名字,比如"todos/todoAdded"。我们通常把那个类型的字符串写成“域/事件名称”,其中第一部分是这个 action 所属的特征或类别,第二部分是发生的具体事情。

action 对象可以有其他字段,其中包含有关发生的事情的附加信息。按照惯例,我们将该信息放在名为 payload 的字段中。

const addTodoAction = {
  type: 'todos/todoAdded',
  payload: 'Buy milk'
}

reducer

reducer 是一个函数,接收当前的 state 和一个 action 对象,必要时决定如何更新状态,并返回新状态。函数签名是:(state, action) => newState你可以将 reducer 视为一个事件监听器,它根据接收到的 action(事件)类型处理事件。

const reducer = function reducer(state = initial, action) {
    state = { ...state };
    switch (action.type) {
        case 'increase':
            state.count++;
            break;
        default:
    }
    // return的内容,会整体替换STORE容器中的状态信息
    return state;
};

运行流程

第一步 创建全局公共的答器 用来存储各组件需要的公共信息

const store = createStore(reducer);

第二步 在组件内部获取公共状态信息,然后渲染

let { count } = store.getState()

第三步 监听组件内公共状态的变化,将方法放入公共容器的事件池内

store.subscribe(函数)

第四步 创建 reducer,就上面写到的

第五步 派发任务,通知reducer执行修改的状态

store.dispatch({
    type: 'increase'
});

这里先将store传入,然后获取,这里通过的是上下文React.createContext()传递数据[store]

上下文传值具体在 React 父子、跨层级 组件通信了解及使用补充了,具体可以查看

redux在运行时会在内部进行一次派发,获取数据默认值

全量代码

目录结构

Redux了解、安装及简单使用

这里的 ThemeContext 是借助 上下文传递store

代码:

index.js

import React from 'react';
import ReactDOM from 'react-dom/client';
// antd汉化
import { ConfigProvider } from 'antd'
import zhCN from 'antd/locale/zh_CN';
import Demo from './views/test-redux/Demo';
import ThemeContext from './ThemeContext';
import store from './store';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <>
    <ConfigProvider locale={zhCN}>
      <ThemeContext.Provider value={{ store }}>
        <Demo />
      </ThemeContext.Provider>
    </ConfigProvider>
  </>
);

ThemeContext.js

import React from "react";

const ThemeContext = React.createContext();

export default ThemeContext;

store/index.js

import { legacy_createStore as createStore } from 'redux';

let initial = {
    count: 0
};
const reducer = function reducer(state = initial, action) {
    console.log("action", action);
    state = { ...state };
    switch (action.type) {
        case 'increase':
            state.count++;
            break;
        case 'decrease':
            state.count--;
            break;
        default:
    }
    // return的内容,会整体替换STORE容器中的状态信息
    return state;
};

/* 创建STORE公共容器 */
const store = createStore(reducer);
export default store;

test-redux/Demo.jsx

import React, { useContext, useEffect, useState } from 'react'
import DemoMain from './DemoMain';
import DemoChange from './DemoChange';
import ThemeContext from '../../ThemeContext';

export default function Demo() {
    const { store } = useContext(ThemeContext)
    let { count } = store.getState()

    // 组件更新操作
    const [_, setNum] = useState(0)
    useEffect(() => {
        store.subscribe(() => {
            setNum(new Date())
        })
    }, [])
    return (
        <div>
            <div>总计:{count}</div>
            <DemoMain />
            <DemoChange />
        </div>
    )
}

test-redux/DemoMain.jsx

import React, { Component } from 'react'
import ThemeContext from '../../ThemeContext'

export default class DemoMain extends Component {
    static contextType = ThemeContext;

    componentDidMount() {
        // 组件更新
        let { store } = this.context
        store.subscribe(() => {
            this.forceUpdate()
        })
    }
    render() {
        let { store } = this.context
        let { count } = store.getState();
        return (
            <div style={{ margin: '20px 0' }}>
                展示内容:{count}
            </div>
        )
    }

}

test-redux/DemoChange.jsx

import React, { Component, useContext } from 'react'
import { Button } from 'antd'
import ThemeContext from '../../ThemeContext';

export default function DemoChange() {
    let { store } = useContext(ThemeContext)
    return (
        <div>
            <Button type="primary" onClick={() => {
                store.dispatch({
                    type: 'increase'
                });
            }}>增加</Button>&nbsp;
            <Button type="primary" onClick={() => {
                store.dispatch({
                    type: 'decrease'
                });
            }}>减少</Button>
        </div>
    )
    // }

}

运行结果:

Redux了解、安装及简单使用

点击增加,数字加1

但是这里可以看到,加在 reducer 内的action在初始化的时候被派发了一次,说明页面在第一次加载的情况下,dispatch派发了此次给state赋初始值

redux为什么不能直接修改状态值?

官方给的是 如果想改变状态state(不能直接改),需要使用store提供的dispatch方法,去派发一个action(动作)。这个动作由Aaction Creators来创建一个对象,将动作派发出去,通知这个store进行修改,store修改不是自己进行修改,是通过Reducers进行状态改变,在Reducers改变状态以后,要通知store,因为store内可能会挂载特别的订阅,这里的订阅会通知组件去做更新。这个就是一个完整的单向数据流。

原因: 如果直接修改,公共状态的变量都分布在各个组件了,不利于维护、管理和逻辑复用 ,而且状态不利于追踪修改位置。

转载自:https://juejin.cn/post/7246955055110045733
评论
请登录