React Hooks:旧状态值持续关闭

时间:2019-03-08 04:27:23

标签: javascript reactjs react-hooks

好的,我意识到这将是一个超长的例子,但是我对此完全感到困惑,因此我想与所有人共享它并尝试找到解决方案。

因此,我尝试在您要在其中输入内容的地方制作一个“标签输入”组件,并且每当您键入空格时,它都会将该字符串附加到您要传递的列表中。为了删除其中一个“标签”,清除内容可编辑区域,按一下退格键以“准备”列表中的最后一个标签以进行删除,然后再次确认删除。在上下文中这很有意义,但是为了示例起见,我编写了一个简化版本。我有以下codeandbox: https://codesandbox.io/s/8q0q3qw60

现在,这是我不了解的部分。

除了实际删除标记外,所有内容似乎都可以正常工作。出于某种原因,我可以适当地“准备”要删除的最后一个标记,但是,当我再次单击退格键以确认时,由于某种原因,prepTagForRemoval的状态(来自挂钩)是闭包的keyDown回调。内容可编辑区域从不更改。它始终为假,但仅在回调内!导致该标签在确认删除后再也不会被适当删除。

为了对此进行复制...

  1. 打开代码沙箱链接
  2. 点击红色轮廓框(内容可编辑的div)
  3. 键入“ hello”(不带引号,所以您好后跟一个空格
  4. 您好,您将移至上方显示“标签:”的行
  5. 单击退格一次
  6. 已准备好删除,并且“ hello”以红色突出显示
  7. 再次单击退格

目前,这时它应该已经从“ Tags:”行中删除了“ hello”,但是实际行为是,它只是将prepForRemoval设置为false,然后再次变成了黑色,而无需从“代码:”中删除“ hello”

对不起,如果这令人困惑,我很乐意尝试澄清更多。我真的很想让此示例正常工作,并在发出第二个删除时删除最后一个标签(或至少调用onRemove)。希望有人可以帮忙!

1 个答案:

答案 0 :(得分:2)

这是react-contenteditable中的错误。以下是其shouldComponentUpdate方法。它不会检查onKeyDown的更改,并且由于退格键不会导致该值的任何更改,因此它不会重新呈现,因此它使用的是handleKeyDown函数的陈旧版本

  shouldComponentUpdate(nextProps: Props): boolean {
    const { props } = this;
    const el = this.getEl();

    // We need not rerender if the change of props simply reflects the user's edits.
    // Rerendering in this case would make the cursor/caret jump

    // Rerender if there is no element yet... (somehow?)
    if (!el) return true;

    // ...or if html really changed... (programmatically, not by user edit)
    if (
      normalizeHtml(nextProps.html) !== normalizeHtml(el.innerHTML)
    ) {
      return true;
    }

    // Handle additional properties
    return props.disabled !== nextProps.disabled ||
      props.tagName !== nextProps.tagName ||
      props.className !== nextProps.className ||
      props.innerRef !== nextProps.innerRef ||
      !deepEqual(props.style, nextProps.style);
  }

此处正在使用react-contenteditable的固定副本:https://codesandbox.io/s/o41yjr3r3q

我将shouldComponentUpdate的最后一部分更改为添加props.onKeyDown !== nextProps.onKeyDown

return (
  props.disabled !== nextProps.disabled ||
  props.tagName !== nextProps.tagName ||
  props.className !== nextProps.className ||
  props.innerRef !== nextProps.innerRef ||
  props.onKeyDown !== nextProps.onKeyDown ||
  !deepEqual(props.style, nextProps.style)
);