const Redux = require('redux');
const reducer = function(state, action) {
if (action.type === 'changeName') {
// const newState = JSON.parse(JSON.stringify(state));
// 不能直接修改原来的state对象
return Object.assign({}, state, {name: action.name});
} else {
// 未配置情况,返回原来的state
return state;
}
}
// 参数: reducer(return state), [init state]
const store = Redux.createStore(reducer, {name: 'init name', age: 20});
// 订阅监听
store.subscribe(() => console.log(store.getState()));
// 同步dispatch
const action = {
changeName() {
return {
type: 'changeName',
name: 'lily'
}
},
increment (number) {
return {
type: "increment",
data: number
}
}
}
store.dispatch(action);
redux中, Redux API主要有:
1. createStore()
2. applyMiddleware()
3. combineReducers()
// combineReducers 实现原理 // 将各个reducer函数包裹在一个对象中,最后通过生成一个新reducer函数 // function combineReducers(reducers) { // return function reducer(state, action) { // let newState = {}; // for (let key in reducers) { // 把state中每一个属性值作为state,带入对应的Reducer中进行处理 // newState[key] = reducers[key](state[key],action); // } // } // }
const Redux = require('redux');
// const state = { a: [], b: [], c:{ name: '', group: []} };
const aReducer = function(state, action) {
if (typeof state === 'undefined') return [];
switch (action.type) {
case 'a':
return state.concat([action.data]);
default:
return state;
}
}
const bReducer = function(state, action) {
if (typeof state === 'undefined') return [];
switch (action.type) {
case 'b':
return state.concat([action.data]);
default:
return state;
}
}
const cNameReducer = function(state, action) {
if (typeof state == 'undefined') return '';
switch (action.type) {
case 'c':
return action.name;
default:
return state;
}
}
const cGroupReducer = function(state, action) {
// state对应的是group的value
if (typeof state === 'undefined') return [];
switch(action.type) {
case 'c':
return state.concat(action.item);
default:
return state;
}
}
const cReducer = function (state, action) {
// state对应的是c的value
if (typeof state === 'undefined') return {name: '', group: []};
switch(action.type) {
case 'c':
// 返回reducer处理函数,然后调用
return Redux.combineReducers({name: cNameReducer, group: cGroupReducer})(state, action);
default:
return state;
}
}
// 每个属性对应的reducer
const reducers = Redux.combineReducers({a: aReducer, b: bReducer, c: cReducer});
const store = Redux.createStore(reducers, {a: [111], b: [222], c:{ name: 'hi', group:[] }});
store.subscribe(() => console.log(store.getState()));
const action1 = {
type: 'b',
data: 'lead'
};
const action2 = {
type: 'a',
data: 'tail'
}
const action3 = {
type: 'c',
name: 'jkp',
item: 'pp'
}
store.dispatch(action1);
store.dispatch(action2);
store.dispatch(action3);
store API包括以下几个:
1. getState()
2. subscribe(callback)
3. dispatch(action)
Redux默认只支持同步action[返回对象](即:dispatch本身只能进行同步触发),若要实现异步action,需要借助一些特殊的插件,如redux-thunk,redux-promise。
let action = { // 同步action,返回一个对象 increment (number) { return { type: "increment", data: number } }, // 异步action, 返回一个函数 asyncIncrement (number) { return dispatch => { // 函数内部执行异步操作 setTimeout(() => { // dispatch一个同部的action对象 dispatch({ type: "increment", data: number }) }, 1000); } }, }
与此同时,在createStore()加入第二个参数--中间件 Redux.applyMiddleware(xxx)
const thunk = require("redux-thunk").default;
const store = Redux.createStore(reducer, Redux.applyMiddleware(thunk));
这里提一下‘redux-thunk'这个中间件的使用[转自:https://juejin.im/post/6844903505199628301]
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import rootReducer from './reducers/index';
//注册thunk到applyMiddleware
const createStoreWithMiddleware = applyMiddleware(
thunk
)(createStore);
const store = createStoreWithMiddleware(rootReducer);
//action方法
function increment() {
return {
type: INCREMENT_COUNTER
};
}
//执行一个异步的dispatch
function incrementAsync() {
return dispatch => {
setTimeout(() => {
dispatch(increment());
}, 1000);
};
}
源码分析
// thunk-redux 源码 function createThunkMiddleware(extraArgument) { // 将dispatch和getState传入action,next()和action()是redux提供的方法。 return ({ dispatch, getState }) => next => action => { // 接着做判断,如果action是一个function,就返回action(dispatch, getState, extraArgument),否则返回next(action) if (typeof action === 'function') { return action(dispatch, getState, extraArgument); } return next(action); }; }
const thunk = createThunkMiddleware(); // 给thunk设置一个属性withExtraArgument,并且将createThunkMiddleware整个函数赋给它。 thunk.withExtraArgument = createThunkMiddleware; export default thunk;
总结:thunk是一个中间函数,它的返回值是一个函数表达式。action里面可能传递多个参数,我们不可能再专门替每个action写一个传递方法。那么就有了thunk的出现,thunk可以将多个参数的函数作为一个参数传递。
例如有这样一个action
function test(arg1, arg2, ...) { return { type: "TEST", arg1, arg2, ... } }
然后我们在执行dispatch()方法是,需要把test()的返回值作为参数传递。这样就解决了多参数传递的问题,这个test()就成了一个thunk。
promise实现异步触发
// 借助promise实现异步触发 function callAction() { const actionPromise = new Promise((resovle, reject) => { const action = { type: 'changeName', name: 'lily' }; resovle(action); }) actionPromise.then((action) => { store.dispatch(action); }) } callAction();
PS: redux-devtools下载安装 https://github.com/zalmoxisus/redux-devtools-extension/releases
然后在项目目录下npm i redux-devtools-extension --save-dev
import {composeWithDevTools} from 'redux-devtools-extension';
const store = Redux.createStore(reducer, composeWithDevTools(Redux.applyMiddleware(thunk)));