REDUX:通过 this.props 访问的存储变量已过时,但 store.getState() 有效

Posted

技术标签:

【中文标题】REDUX:通过 this.props 访问的存储变量已过时,但 store.getState() 有效【英文标题】:REDUX: store variables accessed via this.props are outdated but store.getState() works 【发布时间】:2020-02-28 09:38:35 【问题描述】:

你好!

通过mapStateToProps 访问存储变量,我遇到了一些以前从未遇到过的问题。也就是说,它们永远不会改变,并且总是在以任何方式更改它们之前在商店中设置它们的默认值。如果我通过store.getState().reducer.x 给他们打电话,我的代码就可以工作!

这是我的商店:

export const initialState = 
    isKeyManagementWindowOpen: false
;

const rootReducer = combineReducers(
    some: someReducer,
    settings: settingsComponentReducer
);

const store = createStore(rootReducer, compose(applyMiddleware(thunk), window.__REDUX_DEVTOOLS_EXTENSION__ ? window.__REDUX_DEVTOOLS_EXTENSION__() : variable => variable));

export default store;

settingsComponentActions.js

export const TOGGLE_KEY_MANAGEMENT_WINDOW = 'TOGGLE_KEY_MANAGEMENT_WINDOW';

export const toggleKeyManagementWindow = isKeyManagementWindowOpen => 
  return  type: TOGGLE_KEY_MANAGEMENT_WINDOW, isKeyManagementWindowOpen;

settingsComponentReducer.js

export const settingsComponentReducer = (state = initialState, action) => 
  console.log(action);
  switch (action.type) 
    case Actions.TOGGLE_KEY_MANAGEMENT_WINDOW:
      return Object.assign(, state, 
        isKeyManagementWindowOpen: action.isKeyManagementWindowOpen
      );
    default: return state;
  
;

可能导致问题的一件事是我在 websocket's subscribe 方法中调用了 this.props

Key.js

connectToWebsocket = ip => 
      const stompClient = Stomp.client(`url/receivekey`);
      stompClient.heartbeat.outgoing = 0;
      stompClient.heartbeat.incoming = 0;
      stompClient.debug = () => null;
      stompClient.connect( name: ip , frame => this.stompSuccessCallBack(frame, stompClient), err => this.stompFailureCallBack(err, ip));
  

stompSuccessCallBack = (frame, stompClient) => 
    stompClient.subscribe(KEY_READER_NODE, keyData => 
      if (!this.props.isKeyManagementWindowOpen) 
        this.loginWithKey(keyData.body);
       else 
        this.addToKeyList(keyData.body);
      
    );
  

即使我事先将isKeyManagementWindowOpen 设置为true,它仍然解析为false。如果我将!this.props.isKeyManagementWindowOpen!store.getState().settings.isKeyManagementWindowOpen 交换,则代码可以工作并进入this.addToKeyList(keyData.body)

所以,如果我交换这些,但将 this.addToKeyList 中的每个商店调用保留为 this.props.,那么这些也是默认值,这没有任何意义。仅当我将每个 this.props. 行与 store.getState()... 交换时才有效。

const mapStateToProps = state => (
    ...
    ...
    isKeyManagementWindowOpen: state.settings.isKeyManagementWindowOpen,
);

export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Key));

到目前为止,我的代码有效,但我想将 props 称为 this.props...,而不是通过 store.getState()...。知道为什么会发生这种情况吗?

谢谢!

【问题讨论】:

【参考方案1】:

好像你在使用深度状态

Object assign 只制作对象的浅拷贝。因此,让我们尝试消除最简单的可能原因。

export const settingsComponentReducer = (state = initialState, action) => 
  const newState = JSON.parse(JSON.stringify(state));

然后使用 newState 代替下面的 state。 这将对您的状态进行深层复制,并且始终是一个新对象,强制您的应用将其视为新道具并正确重新渲染。

【讨论】:

【参考方案2】:

为什么不使用这样的东西,因为您不应该直接改变应用程序的整体状态,只有在触发操作时才更新它,而是在更新之前传播原始状态。

export const settingsComponentReducer = (state = initialState, action) => 
  console.log(action);
  switch (action.type) 
    case Actions.TOGGLE_KEY_MANAGEMENT_WINDOW:
      return 
        ...state,
        isKeyManagementWindowOpen: action.isKeyManagementWindowOpen
      );
    default: 
      return state;
  
;

【讨论】:

所以我总是用Object.assign 改变状态? This redux 的文章说它只是复制值和更新。我很困惑。 抱歉,它不会直接改变状态。但类似于 Joe Lloyd 的回答, Object.assign 将创建状态的副本。据我所知,最好的做法是在更新之前使用扩展 ... 运算符拉入现有值。您是否尝试过使用 spread 而不是 Object.assign 并测试了输出的差异还是同样的问题? 没问题!这是我接下来要尝试的,然后再报告。 我回答了 props 与 this.props 的使用。根据我的记忆,只有在使用 super(props) 时才能使用 this.props。当使用 Redux 来存储我们的全局状态时,我们倾向于只使用 props。您可以更进一步,通过从有利有弊的 mapStateToProps 解构它来移除道具。优点是你只需要你想要的状态到组件而不是映射整个全局应用程序状态,更少的击键(有时更多的头发拉)。缺点 - 可读性,有时在查看代码以查看其来源时,实际上看到 props 一词确实会有所帮助。【参考方案3】:

问题在于,在下一行代码执行之前,React 无法更新this.props中的任何值。

这实际上不是 Redux 特有的问题。在 any React 组件中,在一行上触发状态更改仍然会在下一行产生相同的 propsstate 值,因为当前函数仍在执行,React 还没有重新- 尚未渲染。

【讨论】:

以上是关于REDUX:通过 this.props 访问的存储变量已过时,但 store.getState() 有效的主要内容,如果未能解决你的问题,请参考以下文章

如何使用带 Redux 的连接从 this.props 获得简单的调度?

在 componentWillMount 的 redux 检查状态

This.props.dispatch 不是函数 - React-Redux

React Redux - this.props.actions.fetchPosts 不是函数

React Redux Firebase 无法获取 firebase.storage

mapDispatchToProps 不工作。 props 为空(错误:redux action 不是函数)