Redux 概念和基本用法

前言

本文主要以 Rudex 结合 Racte 的方式,对 Redux 的基本概念和用法进行记录;

Rudex 是什么

Rudex 是一个以集中式 Store 的方式对整个应用中使用的状态进行集中管理,确保状态只能以可预测的方式更新;
简单来讲:Rudex 是一个状态管理库;
明确了 Rudex 是什么之后,需要思考两个问题:

  1. 为什么要使用 Rudex?
  2. 什么时候应该使用 Rudex?

Redux 设计理念

Redux 工作流

  1. 应用程序中发生了某些事情,例如用户单击按钮,用户发出 Action
  2. Store 自动调用 Reducer,并且传入两个参数:当前 State 和收到的 Action; Reducer 会返回新的 State ;
  3. 组件内部通过订阅 store 中的状态 state 来刷新自己的视图

Rudex 三大原则

  1. 单一数据源
    整个应用的 state 被储存在一个状态树中,并且这个状态树只存在于唯一的 store 中;
  2. State 是只读的
    唯一改变 state 的方法就是触发 action,action 是一个用于描述已发生事件的普通对象;
  3. 使用纯函数来修改
    为了描述 action 如何改变 state tree,你需要编写纯的 reducers;

安装

Rudex 核心

npm install redux --save

基本概念和API

提示:本节的示例和说明只需要安装 Redux 核心就可以了;

  1. Store
    Store 是保存数据的地方,它是一个对象,一个应用只能有一个 Store;
    Rudex 提供了一个叫 createStore 的方法用来生成 Store;

    import { createStore } from 'redux';
    const store = createStore(fn);
    

    上面代码中,createStore 方法接收一个函数作为参数,返回一个 Store 对象;

  2. State
    Store对象包含所有数据, State 代表某个时间点的 Store, 用来描述应用程序在特定时间点的状况;
    获取当前时间点的 State: store.getState()

    import { createStore } from 'redux';
    const store = createStore(fn);
    
    const state = store.getState();
    

    Redux 规定一个 state 对应一个 View, 只要 state 相同,view 就是一样的,反过来也一样;

  3. Action
    State 的变化会导致 View 变化,但是用户接触不到 State,只能通过 View 发出一个由 Rudex 提供的一个叫 Action 的通知来告诉 Store, State 要发生变化了;
    Action 是一个对象;Action 对象中的 type 属性是必须的,表示 Action 的名称,其他属性可以根据需求自由设置;

    const action = {
    	type: 'counter/add',
    	payload: 'Add Operation'
    };
    

    上面代码中,Action 的名称是 counter/add, 携带的数据是字符串 Add operation, Action描述当前发生的事情,这是改变 State 的唯一的方式;

  4. Action Creator
    View 可能会发很多种通知,会导致有多种 Action,可以定义一个函数生成 Action, 这个函数就叫 Action Creator;

    const add_counter = 'counter/add';
    
    function addCounter(text) {
    	return {
    		type: add_counter,
    		text
    	}
    }
    
    const action = addCounter('Add Operation');
    

    上面代码中,addCounter 函数就是一个 Action Creator;

  5. store.dispatch()
    store.dispatch() 是 View 发出 Action 的唯一方法;

    import { createStore } from 'redux';
    const store = createStore(fn);
    
    store.dispatch({
      type: 'counter/add',
      payload: 'Add Operation'
    })
    

    上面代码中,store.dispatch() 接收一个 Action 对象作为参数,将它发送出去;
    结合 Action Creator,可以改写成这样:

    const action = addCounter('Add Operation');
    store.dispatch(action);
    
  6. Reducer
    Store 收到 Action 以后,必须给出一个新的 State,这样 View 才会发生变化;这种 State 的计算过程 就叫做 Reducer;
    Reducer 是一个纯函数,接收 Action 和当前 State 作为参数,决定如何更新状态,返回一个新的 State;

    注意:Reducer 必须是一个纯函数,也就是说函数返回的结果必须由参数 state 和 action 决定,而且不产生任何副作用也不能修改 state 和 action 对象;

    const reducer = (state, action) => {
    	switch (action.type) {
    		case 'counter/add':
    			return new state;
    		default:
    			return state;
    	}
    };
    

    实际应用中,store.dispatch 方法会触发 Reducer 的自动执行; 为此,Store 需要知道 Reducer 函数,做法就是在生成 Store 的时候,将 Reducer 函数传入 createStore 方法;

    import { createStore } from 'redux';
    const store = createStore(reducer);
    

    上面代码中,createStore 接收 Reducer 作为参数,生成一个新的 Store,以后每当 store.dispatch 发送过来一个新的 Action,就会自动调用Reducer,得到新的 State;

  7. store.subscribe()
    Store 允许使用 store.subscribe 方法设置监听函数,一旦 State 发生变化,就自动执行这个函数;

    import { createStore } from 'redux';
    const store = createStore(reducer);
    
    store.subscribe(listener);
    

    只要把 View 的更新函数放入 listen, 就会实现 View 的自动渲染;
    store.subscribe 方法返回一个函数,调用这个函数就可以解除监听;

    const unsubscribe = store.subscribe(() =>
      console.log(store.getState())
    );
    
    unsubscribe();
    

一个计数器示例:

点击查看代码
import React from 'react';
import ReactDOM from 'react-dom/client';
import { createStore } from 'redux';

const root = ReactDOM.createRoot(document.getElementById('root'));
const Counter = (props) => {
  const {value, onAdd, onRemove} = props;
  return (
    <div>
      <span>{value && value.counter}</span>
      <button onClick={onAdd}>增加</button>
      <button onClick={onRemove}>减少</button>
    </div>
  );
}
const defaultState = {
  counter: 0
}
const reducer = (state = defaultState, action) => {
  switch (action.type) {
    case "counter/add":
      return { ...state, counter: state.counter + 1 };
    case "counter/remove":
      return { ...state, counter: state.counter - 1 };

    default:
      return state;
  }
}
const store = createStore(reducer);

const render = () => {
  root.render(
    <React.StrictMode>
      <Counter
        value={store.getState()}
        onAdd={() => store.dispatch({type: 'counter/add'})}
        onRemove={() => store.dispatch({type: 'counter/remove'})} />
    </React.StrictMode>
  );
}

render();
store.subscribe(render);

小结

  • Redux 使用 "单向数据流"
    • State 描述了应用程序在某个时间点的状态,UI 基于该状态渲染
    • 当应用程序中发生某些事情时:
      • UI dispatch 一个 action
      • store 调用 reducer,随后根据发生的事情来更新 state
      • store 通知 UI state 发生了变化
    • UI 基于新 state 重新渲染
  • Redux 有这几种类型的代码
    • Action 是有 type 字段的纯对象,描述发生了什么
    • Reducer 是纯函数,基于先前的 state 和 action 来计算新的 state
    • 每当 dispatch 一个 action 后,store 就会调用 reducer

使用 React-Redux

介绍

React-Redux 是 Redux 的官方 React 绑定库;它能够使你的 React 组件从 Redux store 中读取数据,并且向 store 分发 actions 以更新数据;

安装

适用于 React 的 Redux 依赖包

npm install react-redux --save

使用 Redux Toolkit

安装

在既有项目上添加 Rudex Toolkit 依赖

npm install @reduxjs/toolkit --save

重新创建一个 React Rudex 应用

npx create-react-app my-app --template redux

未完待续。。。

学习与参考文档

posted @ 2022-11-09 13:30  太轻描淡写了  阅读(568)  评论(0编辑  收藏  举报