React核心功能:Redux状态管理

1. Redux介绍

React只是一个DOM的抽象层,对于大型项目将会遇到组件之间的通信代码结构等问题。而Redux将能解决状态管理问题,它用于中大型,数据比较庞大,组件之间数据交互多的情况下使用。但注意Redux的使用,Redux的创造者说过:

“如果你不知道是否需要 Redux,那就是不需要它。” “只有遇到 React 实在解决不了的问题,你才需要 Redux 。”

Redux适用以下场景:(多交互,多数据源)

  • 用户的使用方式复杂
  • 不同身份的用户有不同的使用方式(比如普通用户和管理员)
  • 多个用户之间可以协作
  • View要从多个来源获取数据

组件的角度:

  • 某个组件的状态,需要共享
  • 某个状态需要在任何地方都可以拿到
  • 一个组件需要改变全局状态
  • 一个组件需要改变另一个组件的状态

2.重要概念

2.1 Store

理解:数据仓库,保存数据的地方。整个应用只能有一个Store。

Redux提供了API:createStore,用于生成Store。

示例:

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

createStore函数接收一个函数作为参数,返回新生成的Store对象。

2.2 State

理解:Store对象包含所有数据。如果想要得到某个时间点的数据,就要对Store生成快照。这种时间点得数据集合,就叫做State。当前时刻的State可以通过store.getState()获取。

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

Redux 规定, 一个 State 对应一个 View。只要 State 相同,View 就相同。你知道 State,就知道 View 是什么样,反之亦然。

2.3 Action

理解:一个对象。当View的某个操作会导致state的数据发生改变时,那么View就会通过action去通知更新state。

示例:

const action = {
	type:"事件名称",
	payload:"xxxx"//该action携带的信息
}

由于View可以触发的改变state的状态的事件很多,而每个事件都需要一个Action,如果都手写,会很麻烦。可以定义一个函数来生成Action,这个函数就叫做Action Creator.

const ADD_TODO = '添加 TODO';

function addTodo(text) {
  return {
    type: ADD_TODO,
    text
  }
}

const action = addTodo('Learn Redux');
2.4 store.dispatch()

从上面我们知道action是一个对象,那它想要在View将信息通知给State,就需要有人将action送过去吧,而store.dispacth()是View发出Action的唯一方法。

示例:

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

store.dispatch({
  type: '事件类型',
  payload: 'xxx'
});

上面代码中,store.dispatch接收一个Action对象作为参数,将它发送出去。

2.5 Reducer

Store接收到一个Action后,必须给出一个新的 State,这样 View 才会发生变化。这种 State 的计算过程就叫做 Reducer。

Reducer 是一个函数,它接受 Action 和当前 State 作为参数,返回一个新的 State。

const reducer = function (state, action) {
  // ...
  return new_state;
};

整个应用的初始状态,可以作为 State 的默认值。下面是一个实际的例子。

const defaultState = 0;
const reducer = (state = defaultState, action) => {
  switch (action.type) {
    case 'ADD':
      return state + action.payload;
    default: 
      return state;
  }
};

const state = reducer(1, {
  type: 'ADD',
  payload: 2
});

上面代码中,reducer函数收到名为ADD的 Action 以后,就返回一个新的 State,作为加法的计算结果。其他运算的逻辑(比如减法),也可以根据 Action 的不同来实现。

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

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

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

为什么这个函数叫做 Reducer呢?因为它可以作为数组的reduce方法的参数。请看下面的例子,一系列 Action 对象按照顺序作为一个数组。

const actions = [
  { type: 'ADD', payload: 0 },
  { type: 'ADD', payload: 1 },
  { type: 'ADD', payload: 2 }
];

const total = actions.reduce(reducer, 0); // 3

上面代码中,数组actions表示依次有三个 Action,分别是加0、加1和加2。数组的reduce方法接受 Reducer 函数作为参数,就可以直接得到最终的状态3。

2.6 store.subscribe()

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

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

store.subscribe(listener);

显然,只要把 View 的更新函数(对于 React 项目,就是组件的render方法或setState方法)放入listen,就会实现 View 的自动渲染。

store.subscribe方法返回一个函数,调用这个函数就可以解除监听。

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

unsubscribe();
3. 工作流程

在这里插入图片描述

首先,用户发出 Action。

store.dispatch(action);

然后,Store 自动调用 Reducer,并且传入两个参数:当前 State 和收到的 Action。 Reducer 会返回新的 State 。

let newState = todoApp(oldState, action);

State 一旦有变化,Store 就会调用监听函数。

// 设置监听函数
store.subscribe(listener);

listener可以通过store.getState()得到当前状态。如果使用的是 React,这时可以触发重新渲染 View。

function listerner() {
  let newState = store.getState();
  component.setState(newState);   
}
4.实例:计数器

下面我们来看一个最简单的实例。

const Counter = ({ value }) => (
  <h1>{value}</h1>
);

const render = () => {
  ReactDOM.render(
    <Counter value={store.getState()}/>,
    document.getElementById('root')
  );
};

store.subscribe(render);
render();

上面是一个简单的计数器,唯一的作用就是把参数value的值,显示在网页上。Store 的监听函数设置为render,每次 State 的变化都会导致网页重新渲染。

下面加入一点变化,为Counter添加递增和递减的 Action。

const Counter = ({ value, onIncrement, onDecrement }) => (

{value}

+ -
);

const reducer = (state = 0, action) => {
switch (action.type) {
case ‘INCREMENT’: return state + 1;
case ‘DECREMENT’: return state - 1;
default: return state;
}
};

const store = createStore(reducer);

const render = () => {
ReactDOM.render(
<Counter
value={store.getState()}
onIncrement={() => store.dispatch({type: ‘INCREMENT’})}
onDecrement={() => store.dispatch({type: ‘DECREMENT’})}
/>,
document.getElementById(‘root’)
);
};

render();
store.subscribe(render);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值