【问题标题】:React useState update not updating immediately until I pass a random activator在我通过随机激活器之前,反应 useState 更新不会立即更新
【发布时间】:2021-03-30 08:14:55
【问题描述】:

所以我在测试时发现了一个非常奇怪的 React useState 行为,无法真正解释原因。

所以下面是我的代码。我正在创建一个带有复选框的 React ListItem。由于用户可以选择多个复选框,所以我觉得最好使用数组存储活动索引。并使用 array.includes 函数检查某个索引是否处于活动状态。当我这样做时,我发现数组 useState 没有立即更新,所以我的复选框检查不起作用。但是,我添加了一个如下所示的随机激活器,突然数组及时更新,我的代码开始工作。我希望我的问题很清楚。有人可以解释为什么会这样吗?

我做了更多的测试,发现激活器需要传入索引变量。如果我传入一些随机值会导致不一致的行为

 const [activeIndex, setactiveIndex] = useState([]);
 const [_, activator] = useState(-1);  //If I add this line of code the array gets updated in time

  const ModifyActiveIndex = (index) => {
    activator(index);
    if (!activeIndex.includes(index)) {
      const copy = activeIndex;
      copy.push(index);
      setactiveIndex(copy);
    } else {
  
      const filtercopy = activeIndex.filter((item) => {
        return item !== index;
      });
      setactiveIndex(filtercopy);
    }
  };

  const checkEntityactive = (index) => {
    return activeIndex.includes(index);
  };

  const ProductList = temp.map((element, index) => {
    return (
      <ListItem key={index}>
        <Checkbox
          checked={checkEntityactive(index)}
          onClick={() => ModifyActiveIndex(index)}
        />
      </ListItem>
    );
  });

【问题讨论】:

  • const copy = activeIndex; 不会创建副本,它本质上只是将activeIndex 重命名为copy,数组仍然是相同的引用,所以当你使用@ 时你正在改变你的状态987654325@。您也不需要在执行过滤器时创建copy 变量,因为过滤器方法将为您创建一个新数组
  • 是的,我只是在测试期间添加的那行代码。我可以拿出来。但这并不能解决问题
  • 我猜如果你把它拿出来,那么你可能正在做类似activeIndex.push(index)的事情?如果是这样,那么如果您这样做,您仍然会直接修改状态。您需要创建一个新数组,并将新索引添加到该 setactiveIndex([...activeIndex, index])
  • 是的,我的代码仍然可以工作的唯一方法是添加 activator(index) 行。所有其他更改都可以使代码更简单,但不能解决问题。我只想知道为什么那行代码解决了我的问题
  • 代码执行到copy.push(index);时,状态已经改变,但setactiveIndex(copy)的参数是数组引用,所以直到activator(index);才会重新渲染组件。 activator(index); 将在 copy.push(index); 之后执行,因为 setState 在事件处理程序中是异步的。实际上,如果你删除setactiveIndex(copy);。它仍然有效。

标签: reactjs use-state


【解决方案1】:
const copy = activeIndex;
copy.push(index);
setactiveIndex(copy);

activeIndex是一个数组,不能这样复制。

在第一行中,您创建了一个名为copy 的指针并将其指向activeIndex 位置,因此副本中的每次更改(如第二行中的push())都会直接更改activeIndex,所以你是更改状态,而不在第二行调用 setState。 (这会导致您的应用无法预测)

你可以这样改变这 3 行:

setactiveIndex([...activeIndex, index]);

【讨论】:

  • 好的,谢谢它确实解决了问题,但它没有告诉我为什么添加行 activator(index) 也有效
  • 因为通过调用 'activator(index)' 您正在通过更改索引来强制组件重新呈现,如果没有它,在这种情况下,您不会使用 'setActiveIndex' 更新 'activeIndex' 所以组件一旦进入 if 状态就永远不会更新
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-12-12
  • 2021-05-20
  • 2022-08-14
  • 1970-01-01
  • 1970-01-01
  • 2021-09-10
相关资源
最近更新 更多