reactdispatch函数_使⽤React开发
关于redux
之前写了⼀篇通过⼀个demo了解Redux,但对于redux的核⼼⽅法没有进⾏深⼊剖析,在此重新总结学习,完整的代码看这⾥。(参考了React 技术栈系列教程)
什么情况需要⽤redux?
⽤户的使⽤⽅式复杂
不同⾝份的⽤户有不同的使⽤⽅式(⽐如普通⽤户和管理员)
多个⽤户之间可以协作
与服务器⼤量交互,或者使⽤了WebSocket
View要从多个来源获取数据
简单说,如果你的UI层⾮常简单,没有很多互动,Redux 就是不必要的,⽤了反⽽增加复杂性。多交互、多数据源场景就⽐较适合使⽤Redux。
设计思想:
Web 应⽤是⼀个状态机,视图与状态是⼀⼀对应的。
所有的状态,保存在⼀个对象⾥⾯。
Redux⼯作流程:
⾸先,⽤户发出 Action。
store.dispatch(action);
然后,Store ⾃动调⽤ Reducer,并且传⼊两个参数:当前 State 和收到的 Action。 Reducer 会返回新的 State 。
let nextState = todoApp(previousState, action);
State ⼀旦有变化,Store 就会调⽤监听函数。
// 设置监听函数
store.subscribe(listener);
listener可以通过State()得到当前状态。如果使⽤的是 React,这时可以触发重新渲染 View。
function listerner() {
let newState = State();
component.setState(newState);
}
如果现在没理解以上流程,不要急,看完以下API就差不多能懂得Redux的核⼼机制了。
API
Store
Store 就是保存数据的地⽅,你可以把它看成⼀个容器。整个应⽤只能有⼀个 Store。
Redux 提供createStore这个函数,⽤来⽣成 Store。
下⾯代码中,createStore函数接受另⼀个函数作为参数,返回新⽣成的 Store 对象。
import { createStore } from 'redux';
const store = createStore(fn);
State
Store对象包含所有数据。如果想得到某个时点的数据,就要对 Store ⽣成快照。这种时点的数据集合,就叫做 State。
当前时刻的 State,可以通过State()拿到。
import { createStore } from 'redux';
const store = createStore(fn);
const state = State();
Redux 规定, ⼀个 State 对应⼀个 View。只要 State 相同,View 就相同。你知道 State,就知道 View 是什么样,反之亦然。
Action
State 的变化,会导致 View 的变化。但是,⽤户接触不到 State,只能接触到 View。所以,State 的变化必须是 View 导致的。Action 就是 View 发出的通知,表⽰ State 应该要发⽣变化了。
Action 是⼀个对象。其中的type属性是必须的,表⽰ Action 的名称。其他属性可以⾃由设置,社区有⼀个规范可以参考。
const action = {
type: 'ADD_TODO',
payload: 'Learn Redux'
};
上⾯代码中,Action 的名称是ADD_TODO,它携带的信息是字符串Learn Redux。
可以这样理解,Action 描述当前发⽣的事情。改变 State 的唯⼀办法,就是使⽤ Action。它会运送数据到 Store。
Action Creator
View 要发送多少种消息,就会有多少种 Action。如果都⼿写,会很⿇烦。可以定义⼀个函数来⽣成 Action,这个函数就叫 Action Creator。
const ADD_TODO = '添加 TODO';
function addTodo(text) {
return {
type: ADD_TODO,
text
}
}
const action = addTodo('Learn Redux');
store.dispatch()
store.dispatch()是 View 发出 Action 的唯⼀⽅法。
import { createStore } from 'redux';
const store = createStore(fn);
store.dispatch({
type: 'ADD_TODO',
payload: 'Learn Redux'
});
上⾯代码中,store.dispatch接受⼀个 Action 对象作为参数,将它发送出去。
结合 Action Creator,这段代码可以改写如下。
store.dispatch(addTodo('Learn Redux'));
Reducer
Store 收到 Action 以后,必须给出⼀个新的 State,这样 View 才会发⽣变化。这种 State 的计算过程就叫做 Reducer。
Reducer 是⼀个函数,它接受 Action 和当前 State 作为参数,返回⼀个新的 State。下⾯是⼀个实际的例⼦
const defaultState = 0;
const reducer = (state = defaultState, action) => {
switch (pe) {
case 'ADD':
return state + action.payload;
default:
return state;
}
};
const state = reducer(1, {
type: 'ADD',
payload: 2
});react组件之间通信
上⾯代码中,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。
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.State())
);
unsubscribe();
中间件与异步操作
⼀个关键问题没有解决:异步操作怎么办?Action 发出以后,Reducer ⽴即算出 State,这叫做同步;Action 发出以后,过⼀段时间再执⾏ Reducer,这就是异步。
怎么才能 Reducer 在异步操作结束后⾃动执⾏呢?这就要⽤到新的⼯具:中间件(middleware)。
为了理解中间件,让我们站在框架作者的⾓度思考问题:如果要添加功能,你会在哪个环节添加?
(1)Reducer:纯函数,只承担计算 State 的功能,不合适承担其他功能,也承担不了,因为理论上,纯函数不能进⾏读写操作。
(2)View:与 State ⼀⼀对应,可以看作 State 的视觉层,也不合适承担其他功能。
(3)Action:存放数据的对象,即消息的载体,只能被别⼈操作,⾃⼰不能进⾏任何操作。
想来想去,只有发送 Action 的这个步骤,即store.dispatch()⽅法,可以添加功能。
中间件的⽤法
本⽂不涉及如何编写中间件,因为常⽤的中间件都有现成的,只要引⽤别⼈写好的模块即可。⽐如,上⼀节的⽇志中间件,就有现成的redux-logger模块。这⾥只介绍怎么使⽤中间件。
import { applyMiddleware, createStore } from 'redux';
import createLogger from 'redux-logger';
const logger = createLogger();
const store = createStore(
reducer,
applyMiddleware(logger)
);
上⾯代码中,redux-logger提供⼀个⽣成器createLogger,可以⽣成⽇志中间件logger。然后,将它放在applyMiddleware⽅法之中,传⼊createStore⽅法,就完成了store.dispatch()的功能增强。
这⾥有两点需要注意:
(1)createStore⽅法可以接受整个应⽤的初始状态作为参数,那样的话,applyMiddleware就是第三个参数了。
const store = createStore(
reducer,
initial_state,
applyMiddleware(logger)
);
(2)中间件的次序有讲究。
const store = createStore(
reducer,
applyMiddleware(thunk, promise, logger)
);
上⾯代码中,applyMiddleware⽅法的三个参数,就是三个中间件。有的中间件有次序要求,使⽤前要查⼀下⽂档。⽐如,logger就⼀定要放在最后,否则输出结果会不正确。
异步操作的基本思路
理解了中间件以后,就可以处理异步操作了。
同步操作只要发出⼀种 Action 即可,异步操作的差别是它要发出三种 Action。
操作发起时的 Action
操作成功时的 Action
操作失败时的 Action
以向服务器取出数据为例,三种 Action 可以有两种不同的写法。
// 写法⼀:名称相同,参数不同
{ type: 'FETCH_POSTS' }
{ type: 'FETCH_POSTS', status: 'error', error: 'Oops' }
{ type: 'FETCH_POSTS', status: 'success', response: { ... } }
/
/ 写法⼆:名称不同
{ type: 'FETCH_POSTS_REQUEST' }
{ type: 'FETCH_POSTS_FAILURE', error: 'Oops' }
{ type: 'FETCH_POSTS_SUCCESS', response: { ... } }
除了 Action 种类不同,异步操作的 State 也要进⾏改造,反映不同的操作状态。下⾯是 State 的⼀个例⼦。
let state = {
// ...
isFetching: true,
didInvalidate: true,
lastUpdated: 'xxxxxxx'
};
上⾯代码中,State 的属性isFetching表⽰是否在抓取数据。didInvalidate表⽰数据是否过时,lastUpdated表⽰上⼀次更新时间。
现在,整个异步操作的思路就很清楚了。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论