React Redux mapStateToProps 不会在更新时触发

Posted

技术标签:

【中文标题】React Redux mapStateToProps 不会在更新时触发【英文标题】:React Redux mapStateToProps not firing on update 【发布时间】:2018-02-21 12:10:02 【问题描述】:

我有一个连接的组件,它维护一个显示“状态”以及几个组件之间通信所需的其他一些东西。我有两个连接的组件,它们是这个总体组件的子组件。根据“状态”组件中的标志,一个或其他子组件将呈现。最好只显示代码:

EditorState 组件:

import React from 'react';
import connect from 'react-redux';

import Library from '../library/index';
import Editor from '../editor/index';

import 
  initialize,
  editorState
 from './actions';

class EditorState extends React.Component 
  componentWillMount() 
    const dispatch = this.props;
    dispatch(initialize());
  

  render() 
    const state = this.props;
    switch(state) 
      case editorState.Library:
        return <Library />
      case editorState.Editor:
        return <Editor />
      default:
        return null;
    
  


export default connect(state => 
  return state.EditorStateReducer;
)(EditorState);

EditorState 操作:

export const EDITOR_STATE_INITIALIZE = 'EDITOR_STATE_INITIALIZE';

export const editorState = 
  Library: 'library',
  Editor: 'editor'


export const initialize = (
  type: EDITOR_STATE_INITIALIZE,
  state: editorState.Library
);

EditorState 减速器:

import 
  EDITOR_STATE_INITIALIZE
 from './actions';

const init = () => (
  state: null
);

export default (state = init(), action) => 
  switch(action.type) 
    case EDITOR_STATE_INITIALIZE:
      return 
        ...state, 
        state: action.state
      
    default:
      return ...state
  

库组件:

import React from 'react';
import connect from 'react-redux';

import Page from '../../../components/page/index';

import LibraryItem from '../../../components/library-item/library-item';

import 
  initialize
 from './actions';

class Library extends React.Component 
  componentWillMount() 
    const dispatch = this.props;
    dispatch(initialize());
  

  render() 
    const templates = this.props;

    const editorTemplates = templates.map(template => 
      <LibraryItem template=template />
    );

    return (
      <Page>
        <div className="card-flex library-table">
          editorTemplates
        </div>
      </Page>
    )
  


export default connect(state => 
  return state.LibraryReducer;
)(Library);

库操作:

import 
  client,
  serviceUrl
 from '../../../common/client';

export const LIBRARY_INITIALIZE = 'LIBRARY_INITIALIZE';

export const initialize = () => dispatch => 
  client.get(`$serviceUrl/templates`).then(resp => 
    dispatch(
      type: LIBRARY_INITIALIZE,
      templates: resp.templates
    );
  );

库减速器:

import 
  LIBRARY_INITIALIZE
 from './actions';

const init = () => (
  templates: []
);

export default (state = init(), action) => 
  switch(action.type) 
    case LIBRARY_INITIALIZE:
      return 
        ...state,
        templates: action.templates
      
    default:
      return ...state
  

我遇到的问题是在调度 LIBRARY_INITIALIZE 时没有调用库组件中的 mapStateToProps。我在 EditorState 和 Library 的 mapStateToProps 中都有断点,在 Library reducer 的 LIBRARY_INITIALIZE 开关中有断点。调试页面加载如下:

EditorState mapStateToProps - state.EditorStateReducer.state 为空

EditorState mapStateToProps - state.EditorStateReducer.state == editorState.Library

库 mapStateToProps - state.LibraryReducer.templates == []

Library Reducer Initialize - action.templates == [template1, template2, etc]

EditorState mapStateToProps - state.LibraryReducer.templates == [template1、template2 等]

然后什么都没有。我希望库 mapStateToProps 在此之后也会触发,以便库可以使用模板重新渲染。然而,这并没有发生。为什么这没有发生?我已经准备好把我的头发拉到这个上面了......

【问题讨论】:

【参考方案1】:

您不能 100% 确定在调度调用之后立即呈现更新的状态。 mapStatetoProps 在组件即将重新渲染时调用,这取决于 React 是否批量更新。默认情况下,React 从事件处理程序批量更新。

您可以参考https://github.com/reactjs/react-redux/issues/291

【讨论】:

如果是这种情况,那么为什么 EditorState mapStateToProps 会在调度后被触发并将数据保存在我需要的正确减速器中? mapStateToProps 在调度时为每个订阅者调用,以便可以更新道具,以便 React 可以确定是否重新渲染。情况并非相反。感谢您尝试提供帮助,但这是不正确的。如果是这样,Redux 将无法与 React 一起正常工作。你可以参考markerikson在这个问题中给出的回复:***.com/questions/41646353 所以我做了更多的实验,看看谁在你的链接中回答了这个问题。我向 LibraryReducer 添加了一个 libraryInitialize 变量,然后在 EditorState 上的 componentWillReceive 道具中,如果新的 libraryInitialize 不等于旧的,我将发送一个丢弃动作。果然,库中的 mapStateToProps 使用正确的模板值触发。我将此标记为已接受的答案,因为它正是它。然而,这似乎是 Redux 不能很好地处理分层连接组件的严重限制。 是的,这是真的,当我遇到同样的问题时。我发现触发依赖动作是一种反模式。您应该将您的依赖动作组合在一起,并在减速器中放置尽可能多的业务逻辑,而不是触发一个并等待道具向下流动以触发依赖动作。我希望这是有道理的。 是的,这是有道理的。但是,我尝试这样做的方式不是使用依赖操作。事实上,我必须引入依赖动作才能让它立即工作。我试图做的是在我的两个页面级容器组件之上引入一个***容器组件。然而,它就是这样,由于 react-redux 的这种限制,我将不得不重新考虑我的方法。不过感谢您的帮助。 哇,这太有用了!我已经疯了,因为我不明白为什么 mapStateToProps 不更新我的道具,即使商店已经正确更新,清楚地注意不要通过在减速器中返回一个副本来改变现有状态。但是这个主题的大多数答案都围绕不变性问题而不是围绕这个确切的问题。 mapStateToProps 不一定在每次调度后直接调用的信息对我来说是新的,但非常有用!非常感谢!

以上是关于React Redux mapStateToProps 不会在更新时触发的主要内容,如果未能解决你的问题,请参考以下文章

Redux 进阶之 react-redux 和 redux-thunk 的应用

React之React-redux数据流转流程

react-redux

redux和react-redux

react状态管理器(分模块)之redux和redux + react-redux + reducer和redux + react-redux + reducer分模块 + 异步操作redux-thu

凡尘---react-redux---react