Javascript React/Redux/Reselect-mapStateToProps即使在看到减速器中反映的更改后也会停止触发。

Javascript React/Redux/Reselect-mapStateToProps即使在看到减速器中反映的更改后也会停止触发。,javascript,reactjs,redux,react-redux,reselect,Javascript,Reactjs,Redux,React Redux,Reselect,我搜索了一个类似的问题,但找不到合适的帖子(虽然我怀疑这个问题以前被问过),所以我提前道歉 我已经在几个项目中使用React的Redux,并且刚刚开始在一个学习项目中包括immutable.js和Reselect。我的测试/学习项目只是将一个大型JSON对象加载到状态,然后我使用重新选择来获取它的一部分,然后传递到我的组件中。下面是我正在加载的对象的示例: export const formState = { progress: { groupId: 3, questionI

我搜索了一个类似的问题,但找不到合适的帖子(虽然我怀疑这个问题以前被问过),所以我提前道歉

我已经在几个项目中使用React的Redux,并且刚刚开始在一个学习项目中包括immutable.js和Reselect。我的测试/学习项目只是将一个大型JSON对象加载到状态,然后我使用重新选择来获取它的一部分,然后传递到我的组件中。下面是我正在加载的对象的示例:

export const formState = {
  progress: {
    groupId: 3,
    questionId: 5,
  },
  content: [
    {
      group: { id: 1, name: 'Company', description: 'Data regarding your company.', questions: 2 },
      questions: [
        {
          id: 1,
          type: 'textField',
          label: 'Required *',
          inputLabelProps: { shrink: true },
          text: 'group 1 question 1',
          answer: '',
        },
    ...
    ...
    ...
    ]
  }
此对象通过componentWillMount()中触发的操作加载到状态,该操作随后流经reducer,最终在组件内触发MapStateTrops,如下所示:

const mapStateToProps = (state) => {
   console.log(state);
   return {
     progress: getProgressData(state),
     content: getContentData(state),
   };
 };
这正如预期的那样有效。该组件有两个按钮,用于遍历在上述“总体状态”的内容对象中找到的问题数组

此外,当您按下向前或向后按钮遍历上述问题数组时,progress对象将通过一个操作得到更新,然后通过以下操作在reducer中得到更新:

  switch (action.type) {
    case UPDATE_PROGRESS:
      formState = state.get('formState');
      formState.progress = action.payload;
      console.log(formState);
      return state
        .set('formState', formState);     
这就是奇怪的地方。第一次单击Forward(向前)或Backward(向后)时,它工作,我看到对象得到更新,下一个问题显示在我的组件中。果然

如果我再次单击“上一步”或“下一步”,我会看到操作被触发,我会看到相应的状态反映在reducer中,但我将不再看到MapStateTrops中console.log中的状态。它永远不会到达那一点。你知道我做错了什么吗

注意:我不只是通过以下方式更新reducer中的状态,这似乎有些奇怪: 返回状态 .setIn(['formState','progress',formState)

我最初尝试这样做,但得到的密钥路径无效。考虑到我正在通过fromJS()将初始状态转换为immutable.js映射,这对我来说非常奇怪,因此我认为其中包含的任何内容都将是一个映射或列表或任何合适的内容,因此可以通过这种方式寻址。。。不管怎样,我想一旦我解决了上述问题,我就会解决这个问题。也就是说,除非它们是相关的

一如既往,如果这是一个重复的问题,我们将感谢您的帮助并真诚道歉


谢谢

您不应该更新reducer中的状态。它几乎总是会导致堰行为。您是否尝试返回新对象?i、 e

switch (action.type) {
    case UPDATE_PROGRESS:
      return {
         ...state,
         formState: {
           ...state.formState,
           progress: action.payload
         }
      };
问题 Immutable.js函数Collection.get返回给定键后面的值,在本例中,该键是指向对象的指针。当前,您可以更改该对象,然后使用Collection.set将其重新设置。对象已更改,但指向该对象的指针(存储在您的状态中的值)未更改。因此,您的状态在技术上是不变的,并且您的组件不会更新

出现此问题的原因是您正在Immutable.js集合中存储普通对象。您应该只使用普通对象,或者只使用Immutable.js集合。不要把它们混在一起

修理 选项1:Immutable.js集合 将state.formState也设置为不可变的.js集合。然后通过Immutable.js方法更改它

switch (action.type) {
    case UPDATE_PROGRESS: {
      let formState = state.get('formState');
      formState = formState.set('progress', action.payload)
      console.log(formState);
      return state
        .set('formState', formState);
    }
如果您决定使用Immutable.js,您应该确保不要留下任何普通的javascript对象,因为它们可以绕过Immutable.js提供的保护

选项2:普通对象(推荐) 将状态设置为普通javascript对象

switch (action.type) {
    case UPDATE_PROGRESS: {
      const formState = { ...state.formState };
      formState.progress = action.payload
      console.log(formState);
      return { ...state, formState };
    }

如果您决定不使用Immutable.js,则必须小心不要意外地直接更改状态。最简单的方法是使用扩展语法复制状态:
conststatecopy={…state}

我将尝试一下。最后,在考虑了这个问题之后,我可能不得不找出我的整体状态问题,以及为什么我不能简单地使用.setIn。使用immutable而不使用immutable,似乎我将要做的一切都是一种反模式。我发现我的问题是,当我第一次将大型对象设置为状态时,我没有执行fromJS,这使事情变得奇怪,因为初始状态有这种情况,但后续版本没有。修好之后,我就可以使用.setIn了,一切都很好。谢谢你的反馈。谢谢你的回复。我很快就会深入研究这个建议。我发现我的问题是,当我第一次将大对象设置为我没有执行fromJS的状态时,这让事情变得奇怪,因为初始状态是这样的,但后续版本没有。修好之后,我就可以使用.setIn了,一切都很好。谢谢你的反馈。选择你的答案是最有帮助的,因为它让我找到了正确的答案。