【问题标题】:react redux duplicate keys even when setting a unique key即使在设置唯一键时也对 redux 重复键做出反应
【发布时间】:2019-06-19 07:54:35
【问题描述】:

我有一个包含 6 个对象的数组,它们有一个 uid,没有别的。这样我就可以重复它们并拥有一些占位符内容,直到准备好将对象添加到数组中。选择新对象时,我设置了一个唯一键。但是,如果我两次选择同一个对象,即使我设置了唯一键。似乎更新了重复项的唯一键(即使唯一键不同)。

可能更容易在此处查看正在运行的代码/应用程序,问题的一个示例是单击 squirtle 然后 blastoise,记下显示的 uid。然后再次单击 squirtle,由于某种原因,它会使用新的 squirtles uid 更新旧的 squirtle,从而导致重复键错误。 https://codesandbox.io/s/l75m9z1xwq 或查看下面的代码。 Math.random 只是占位符,直到我可以正常工作。

const initState = {
 party: [
 { uid: 0 },
 { uid: 1 },
 { uid: 2 },
 { uid: 3 },
 { uid: 4 },
 { uid: 5 }
 ]
};

当我点击某个东西时,它会被触发:

handleClick = pokemon => {
   // setup a uid, will need a better method than math.random later
   pokemon.uid = Math.random();

   this.props.addToParty(pokemon);
};

然后这会调用一个触发以下 reducer 的调度。它本质上只是检查对象是否没有正常的 ID,然后用发送的有效负载替换内容。它会这样做,但也会以某种方式更新任何具有相同 uid 的先前对象,即使 if 语句没有针对它们运行。

const rootReducer = (state = initState, action) => {
  if (action.type === "ADD_POKEMON") {
    let foundFirstEmptyPoke = false;

    const newArray = state.party.map((pokemon, index) => {
      if (typeof pokemon.id === "undefined" && foundFirstEmptyPoke === false) {
        foundFirstEmptyPoke = true;
        pokemon = action.payload; // set the data to the first object that ios empty
      }
      // if we get to the last pokemon and it's not empty
      if (index === 5 && foundFirstEmptyPoke === false) {
        pokemon = action.payload; // replace the last pokemon with the new one
      }
      return pokemon;
    });
    return {
      party: newArray
    };
  }
  return state;
};

【问题讨论】:

    标签: javascript reactjs redux react-redux


    【解决方案1】:

    这里的问题是,当你点击选择一个口袋妖怪时,你会改变从 API 检索到的数据:

    handleClick = pokemon => {
      pokemon.uid = Math.random(); // HERE
      this.props.addToParty(pokemon);
    };
    

    你实际上改变了反应状态。你应该做的是克隆你的 pokemon 数据对象,向你刚刚生成的克隆添加一个 uid 并用它更新你的 redux 状态:

    handleClick = pokemon => {
      this.props.addToParty({
        ...pokemon,
        uid: Math.random()
      });
    };
    

    这样,不会保留对实际反应状态的引用。因为这就是你说it updates the old squirtle with the new squirtles uid 时发生的事情。当您尝试添加另一个 pokemon 时,您更新了从 API 检索到的数据,这些数据也从您的第一个 pokemon 插槽(来自您的 redux 状态)中引用。

    【讨论】:

    • 啊,非常感谢,这很有道理。我还是新手,所以真的需要提醒自己永远不要改变任何与状态相关的东西。
    【解决方案2】:

    你正在改变状态。使用扩展语法*** 复制更新前的状态。

    return {
    ...state,
    party: newArray
    }
    

    【讨论】:

      【解决方案3】:

      在 react/redux 中,最好不要改变对象:

      this.props.addToParty({...pokemon, uid: Math.random()});
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-05-18
        • 2013-03-27
        • 2021-09-10
        • 1970-01-01
        • 2019-05-03
        • 2022-07-07
        • 1970-01-01
        • 2011-06-26
        相关资源
        最近更新 更多