反应useState坏了吗?状态未正确更新

时间:2020-04-21 00:52:38

标签: reactjs react-hooks

查看此处:

https://codesandbox.io/s/nervous-hermann-5wsph

基本上:

示例中使用的键盘似乎得到了错误的状态副本

一旦按键盘上的shift键,它便会修复。但是除此之外呢?键盘onKeyPress的useState变量错误。

出什么问题了?

此: enter image description here

调试文本应该在控制台中更改,但不会更改。这意味着我启动onKeyPress的任何内容都将具有错误的状态变量副本,但我在回调中调用的除外。

那是非常非常糟糕。我以为useState将解决这些问题,而不是让它们变得更难?我想念什么吗?

1 个答案:

答案 0 :(得分:3)

问题不是与React状态有关,而是与Keyboard组件有关。

react-simple-keyboard并未意识到道具已经更改,因此您传递的onKeyPress函数始终具有初始值。

当React状态更改(调试文本)时,将使用新值重新创建onKeyPressed组件中的MyComponent函数。反过来,onKeyPress内部的KeyboardWrapper函数也会重新创建。

此新功能作为道具传递给Keyboard,但是在Keyboardsee here)的源代码中进行检查以查看道具是否已更改。

执行此检查的功能可以在here中找到:

export const propsChanged = (prevProps, props) => {
  const cleanProps = sourceObj =>
    JSON.stringify({
      ...sourceObj,
      stateToIgnore: null
    });

  return cleanProps(props) !== cleanProps(prevProps);
};

此功能有一个错误。当“清理”道具时,所有功能都将被删除-这有点愚蠢,因为功能是有效的道具。

因此,先前的道具(包括旧的onKeyPress函数,其初始值为debugText)被“清理”并与新的“清理的”道具进行比较,它看起来{ 1}},因为先前的Keyboard道具或新的clean道具都不具有clean功能,所以道具没有改变。

我在该函数中添加了一些日志记录:

onKeyPress

这是结果:

const previousProps = {
  onKeyPress: () => {
    console.log("Initial text");
  },
};

const newProps = {
  onKeyPress: () => {
    console.log("New text");
  },
};

const propsChanged = (prevProps, props) => {
  const cleanProps = (sourceObj) =>
    JSON.stringify({
      ...sourceObj,
      stateToIgnore: null,
    });

  console.log("original prev props:", prevProps);
  console.log("clean prev props:", cleanProps(prevProps));
  console.log("original new props:", props);
  console.log("clean new props:", cleanProps(props));

  return cleanProps(props) !== cleanProps(prevProps);
};

console.log(
  "does keyboard think props have changed?",
  propsChanged(previousProps, newProps)
);

console.log("have props actually changed?", previousProps !== newProps);

console.log("is there a bug with react-simple-keyboard?", true);

我建议在their github repo上提出问题。