onKeyUp 在 React 中不起作用,而 onChange 起作用了

onKeyUp not working in React where onChange did

我正在做一个 React 编码挑战,需要在 KeyUp 上更新一个值。我最初将其设置为更新 onChange,但测试需要 onKeyUp,所以我尝试将其更改为那个,但我的字段不再更新,我无法在文本区域中输入任何内容。

class MarkdownApp extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      value: ''
    };

    this.handleKeyUp = this.handleKeyUp.bind(this);
  }

  handleKeyUp(event) {
    this.setState({ value: event.target.value })
  }

  render() {
    return (
      <form>
        <label>
          Enter your markdown here:
          <br />
          <textarea value={this.state.value} onKeyUp={this.handleKeyUp} id='editor' />
          <br />
        </label>
        <label>
          Your markup will be previewed here:
          <p id='preview'>{marked(this.state.value)}</p>
        </label>
      </form>
    );
  }
}

ReactDOM.render(
  <MarkdownApp />,
  document.getElementById('root')
);

就像我说的,当它是 onChange 并且我的函数是 handleChange 时它工作正常,但是因为我切换它我不能输入任何东西。

由于事件发生在文本框的实际值更改之前,因此 event.target.value 的结果是一个空字符串。使用空字符串设置状态,清除文本框。

您需要从事件中获取按下的键值,并将其添加到现有的state.value

注意:我已经从演示中删除了 marked

class MarkdownApp extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      value: ''
    };

    this.handleKeyUp = this.handleKeyUp.bind(this);
  }

  handleKeyUp(event) {
    const keyValue = event.key;
    
    this.setState(({ value }) => ({
      value: value + keyValue
    }))
  }

  render() {
    return (
      <form>
        <label>
          Enter your markdown here:
          <br />
          <textarea value={this.state.value} onKeyUp={this.handleKeyUp} id='editor' />
          <br />
        </label>
        <label>
          Your markup will be previewed here:
          <p id='preview'>{this.state.value}</p>
        </label>
      </form>
    );
  }
}

ReactDOM.render(
  <MarkdownApp />,
  document.getElementById('root')
);
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>

<div id="root"></div>

您可以通过不给它 value 并简单地将值存储在 ref 的状态中来使文本区域不受控制。

示例 (CodeSandbox)

class MarkdownApp extends React.Component {
  ref = null;
  state = {
    value: ""
  };

  handleKeyUp = event => {
    this.setState({ value: this.ref.value });
  };

  render() {
    return (
      <form>
        <label>
          Enter your markdown here:
          <br />
          <textarea
            onKeyUp={this.handleKeyUp}
            ref={ref => (this.ref = ref)}
            id="editor"
          />
          <br />
        </label>
        <label>
          Your markup will be previewed here:
          <p id="preview">{marked(this.state.value)}</p>
        </label>
      </form>
    );
  }
}

我只想从文本区域中删除 value 属性。因为如果您将 value 属性放入其中,那么用户将无法以交互方式更改它。该值将始终保持固定(除非您明确更改代码中的值)。您不需要使用 React 来控制它——DOM 将为您保留该值。

我在下面所做的唯一更改是从 textarea 元素中删除 value={this.state.value}

import React from 'react';
import ReactDOM from 'react-dom';

class MarkdownApp extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      value: ''
    };

    this.handleKeyUp = this.handleKeyUp.bind(this);
  }

  handleKeyUp(event) {
    this.setState({ value: event.target.value })
  }

  render() {
    return (
      <form>
        <label>
          Enter your markdown here:
          <br />
          <textarea value={this.state.value} onKeyUp={this.handleKeyUp} id='editor' />
          <br />
        </label>
        <label>
          Your markup will be previewed here:
          <p id='preview'>{this.state.value}</p>
        </label>
      </form>
    );
  }
}

ReactDOM.render(
  <MarkdownApp />,
  document.getElementById('root')
);

问题是您有两种方式将 state = 绑定到文本框中的值。 OnChange 会在进行更改并且事件触发后更新您的状态。 Onkeyup returns 值 onkeyup 并且由于您将其映射到您的状态,因此它将保持为空。删除 value 道具,它应该可以工作。