Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

如何清空 redux 信息? #907

Closed
shenqihui opened this issue May 11, 2017 · 16 comments
Closed

如何清空 redux 信息? #907

shenqihui opened this issue May 11, 2017 · 16 comments

Comments

@shenqihui
Copy link

例如 redux-reset

如何清空 redux 的信息?


使用场景:

一个人员管理多个校区,每个校区的信息不通,切换校区时候,为了避免旧数据造成的问题,只好使用 location.reload() 强制页面刷新以便更新全部内存信息。
想要做到在不刷新页面的清空下,清空 redux 的数据?

@dicklwm
Copy link

dicklwm commented May 11, 2017

我想到一种办法,写一个公用方法,取消注册model,app.unmodel(namespace),再注册回去app.model(model)

@xufei
Copy link
Contributor

xufei commented May 11, 2017

写一个专门的reducer去清?

@nalantianyi
Copy link

@xufei 飞姐,借道问下,dva为什么好久没更新了,在憋大招吗?

@laketea
Copy link

laketea commented May 11, 2017

实际业务中,很多model带有初始state的,单纯的清空state中的数据对象容易出现问题.
我们的做法是,创建model的时候,将model的初始state 克隆一份,然后默认给每个model都添加resetState reducer(reset方法中会将克隆的初始数据 更新到state中),需要清理的时候,只需发送对应action即可 ( xxx/resetState ).
但是如果是全局reset,也还是比较蛋疼,只能每个model都发一个action,不过暂时还没遇到这种需求.

@zjxpcyc
Copy link

zjxpcyc commented May 12, 2017

感觉,不应该会出现这种现象吧。第一个校区的初始化信息,也应该是有 action 吧,切换校区,不应该是也调用这个 action 吗? 即使你全部重置了 state ,切换校区的时候 action 之后,不应该是自动就初始化好了吗?

@shenqihui
Copy link
Author

@laketea @zjxpcyc @xufei 结合你们的意见,觉得也是还是得直接使用 action 来初始化数据才是。

每个 model 都增加个 reload 的方法,切换之后每个去清空。

@dicklwm 不知道 unmodel 会不会有后遗症。所以还是参考他们的做法直接让每个 model reload 重置数据。

谢谢大家。


不过,短期内我还是采用暴力方法直接 reload 页面。等找到更好的方法就补充回来。

@helloyou2012
Copy link
Contributor

如果确实是重置整个 state 那 @xufei 的方法是最简单的:

// const initialState = ...;
const app = dva({
  onReducer: reducer => {
    return (state, action) => {
      if (action.type === 'RESET') {
        return initialState;
      }
      return state;
    };
  }
});
// Usage
dispatch({ type: 'RESET' });

@laozhu
Copy link

laozhu commented Dec 12, 2018

从网上搜过来,照着 @xufei 老大的代码搞了半天,就是跑不起来。花了半天才搞清楚状况,使用 onReducer 的时候除了要返回新的 state,还需要返回一个 routing 才行。参考了 dva/test/reducers-test.js 的代码

本人项目基于 antd-pro,需要在 src 目录下面新增两个文件 app.jsinitialState.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.typeRESET 的时候重置 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' });
    }
  };

  ...
}

@luania
Copy link

luania commented May 28, 2019

在应用开始的时候把初始state存下来,作为reset的数据是否可行

@shangdev
Copy link

shangdev commented Sep 10, 2019

@laozhu

你好,我按照你写的,运行时报错:Uncaught (in promise) Could not find router reducer in state tree, it must be mounted under "router"

也就是 routing 这个在 initialState 对象中没有,这个应该是从哪里定义的?

@wizard-a
Copy link

@shangdev @laozhu dva 升级后出现这个了 index.js:1 uncaught at _callee Could not find router reducer in state tree, it must be mounted under "router"
代码是一样的

@xclw2000
Copy link

从网上搜过来,照着 @xufei 老大的代码搞了半天,就是跑不起来。花了半天才搞清楚状况,使用 onReducer 的时候除了要返回新的 state,还需要返回一个 routing 才行。参考了 dva/test/reducers-test.js 的代码

本人项目基于 antd-pro,需要在 src 目录下面新增两个文件 app.jsinitialState.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.typeRESET 的时候重置 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后,在哪调用的或者说启动的呢?

@MrSeaWave
Copy link

@laozhu 可以去除initialState的定义,当action.typeRESET时,直接使用初始化的数据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' });
    }
  };

  ...
}

@cike8899
Copy link

  • 如果要重置某个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;
    };
  }

@SmallBookworm
Copy link

  • 如果要重置某个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

@cike8899
Copy link

dva-reset-state 一个插件,直接拿过来用,大家可以参考下

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests