例如 redux-reset
如何清空 redux 的信息?
使用场景:
一个人员管理多个校区,每个校区的信息不通,切换校区时候,为了避免旧数据造成的问题,只好使用 location.reload() 强制页面刷新以便更新全部内存信息。
想要做到在不刷新页面的清空下,清空 redux 的数据?
我想到一种办法,写一个公用方法,取消注册model,app.unmodel(namespace)
,再注册回去app.model(model)
写一个专门的reducer去清?
@xufei 飞姐,借道问下,dva为什么好久没更新了,在憋大招吗?
实际业务中,很多model带有初始state的,单纯的清空state中的数据对象容易出现问题.
我们的做法是,创建model的时候,将model的初始state 克隆一份,然后默认给每个model都添加resetState reducer(reset方法中会将克隆的初始数据 更新到state中),需要清理的时候,只需发送对应action即可 ( xxx/resetState ).
但是如果是全局reset,也还是比较蛋疼,只能每个model都发一个action,不过暂时还没遇到这种需求.
感觉,不应该会出现这种现象吧。第一个校区的初始化信息,也应该是有 action 吧,切换校区,不应该是也调用这个 action 吗? 即使你全部重置了 state ,切换校区的时候 action 之后,不应该是自动就初始化好了吗?
@laketea @zjxpcyc @xufei 结合你们的意见,觉得也是还是得直接使用 action 来初始化数据才是。
每个 model 都增加个 reload 的方法,切换之后每个去清空。
@dicklwm 不知道 unmodel 会不会有后遗症。所以还是参考他们的做法直接让每个 model reload 重置数据。
谢谢大家。
不过,短期内我还是采用暴力方法直接 reload 页面。等找到更好的方法就补充回来。
如果确实是重置整个 state 那 @xufei 的方法是最简单的:
// const initialState = ...;
const app = dva({
onReducer: reducer => {
return (state, action) => {
if (action.type === 'RESET') {
return initialState;
}
return state;
};
}
});
// Usage
dispatch({ type: 'RESET' });
从网上搜过来,照着 @xufei 老大的代码搞了半天,就是跑不起来。花了半天才搞清楚状况,使用 onReducer 的时候除了要返回新的 state,还需要返回一个 routing 才行。参考了 dva/test/reducers-test.js 的代码
本人项目基于 antd-pro,需要在 src
目录下面新增两个文件 app.js
和 initialState.js
。
首先,在 ./src/initialState.js
文件中定义初始状态。
import defaultSettings from './defaultSettings';
export default {
setting: defaultSettings,
loading: {
effects: {},
},
global: {
layout: 'basic', // Page layout switch (options: basic | map)
collapsed: false,
notices: [],
},
login: {
status: false,
authority: 'guest',
},
register: {
status: false,
},
}
然后,在 ./src/app.js
文件的 onReducer
钩子中判断,当 action.type
是 RESET
的时候重置 state 树。
import initialState from './initialState';
// eslint-disable-next-line
export const dva = {
config: {
initialState,
onReducer(reducer) {
return (state, action) => {
const newState = action.type === 'RESET' ? initialState : reducer(state, action);
return { ...newState, routing: newState.routing };
};
},
},
};
这样定义好,在需要的地方(比如 logout)就可以直接使用,比如修改 antd-pro 顶部菜单 ./src/layouts/Header.js
的退出登录操作:
class HeaderView extends PureComponent {
...
handleMenuClick = ({ key }) => {
...
if (key === 'logout') {
dispatch({ type: 'RESET' });
dispatch({ type: 'login/logout' });
}
};
...
}
在应用开始的时候把初始state存下来,作为reset的数据是否可行
@laozhu
你好,我按照你写的,运行时报错:Uncaught (in promise) Could not find router reducer in state tree, it must be mounted under "router"
也就是 routing 这个在 initialState 对象中没有,这个应该是从哪里定义的?
@shangdev @laozhu dva 升级后出现这个了 index.js:1 uncaught at _callee Could not find router reducer in state tree, it must be mounted under "router"
代码是一样的
从网上搜过来,照着 @xufei 老大的代码搞了半天,就是跑不起来。花了半天才搞清楚状况,使用 onReducer 的时候除了要返回新的 state,还需要返回一个 routing 才行。参考了 dva/test/reducers-test.js 的代码
本人项目基于 antd-pro,需要在
src
目录下面新增两个文件app.js
和initialState.js
。首先,在
./src/initialState.js
文件中定义初始状态。import defaultSettings from './defaultSettings'; export default { setting: defaultSettings, loading: { effects: {}, }, global: { layout: 'basic', // Page layout switch (options: basic | map) collapsed: false, notices: [], }, login: { status: false, authority: 'guest', }, register: { status: false, }, }
然后,在
./src/app.js
文件的onReducer
钩子中判断,当action.type
是RESET
的时候重置 state 树。import initialState from './initialState'; // eslint-disable-next-line export const dva = { config: { initialState, onReducer(reducer) { return (state, action) => { const newState = action.type === 'RESET' ? initialState : reducer(state, action); return { ...newState, routing: newState.routing }; }; }, }, };
这样定义好,在需要的地方(比如 logout)就可以直接使用,比如修改 antd-pro 顶部菜单
./src/layouts/Header.js
的退出登录操作:class HeaderView extends PureComponent { ... handleMenuClick = ({ key }) => { ... if (key === 'logout') { dispatch({ type: 'RESET' }); dispatch({ type: 'login/logout' }); } }; ... }
你这个有完整的代码吗?在app.js里面定义完dva后,在哪调用的或者说启动的呢?
@laozhu 可以去除initialState
的定义,当action.type
为RESET
时,直接使用初始化的数据reducer({},{type:'@@INIT'})
export const dva = {
config: {
onReducer(reducer) {
return (state, action) => {
const newState = action.type === 'RESET' ? reducer({},{type:'@@INIT'}) : reducer(state, action);
return { ...newState, routing: newState.routing };
};
},
},
};
当需要重置所有的model时
class HeaderView extends PureComponent {
...
handleMenuClick = ({ key }) => {
...
if (key === 'logout') {
dispatch({ type: 'RESET' });
dispatch({ type: 'login/logout' });
}
};
...
}
如果要重置某个namespace下的state直接dispatch 该state对应的reducer就行了。
如果要重置某个namespace下的所有state
onReducer(reducer) {
let initialState: any = null;
return (state: any, action: any) => {
let newState: any = reducer(state, action);
if (action.type === "@@INIT") {
initialState = newState; //缓存所有初始state
}
const actionTypeArr: string[] = action.type.split("/");
if (actionTypeArr.length === 1 && action.type === "reset") {
newState = initialState;
}
if (actionTypeArr.length > 1) {
const namespace = actionTypeArr[0];
const postfix = actionTypeArr[actionTypeArr.length - 1];
const modelState = initialState[namespace];
if (postfix === "reset" && modelState) {
newState = {
...newState,
[namespace]: modelState
}; //重置某个namespace的state,直接dispacth({type:"{namespace}/reset"})
}
}
return newState;
};
}
- 如果要重置某个namespace下的state直接dispatch 该state对应的reducer就行了。
- 如果要重置某个namespace下的所有state
onReducer(reducer) { let initialState: any = null; return (state: any, action: any) => { let newState: any = reducer(state, action); if (action.type === "@@INIT") { initialState = newState; //缓存所有初始state } const actionTypeArr: string[] = action.type.split("/"); if (actionTypeArr.length === 1 && action.type === "reset") { newState = initialState; } if (actionTypeArr.length > 1) { const namespace = actionTypeArr[0]; const postfix = actionTypeArr[actionTypeArr.length - 1]; const modelState = initialState[namespace]; if (postfix === "reset" && modelState) { newState = { ...newState, [namespace]: modelState }; //重置某个namespace的state,直接dispacth({type:"{namespace}/reset"}) } } return newState; }; }
action.type === "@@INIT"我改成action.type.indexOf('@@redux/INIT') === 0
dva-reset-state 一个插件,直接拿过来用,大家可以参考下
Most helpful comment
dva-reset-state 一个插件,直接拿过来用,大家可以参考下