【问题标题】:onKeyUp not working in React where onChange didonKeyUp 不能在 onChange 的 React 中工作
【发布时间】:2018-12-20 02:58:37
【问题描述】:

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

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 时,它​​工作得很好,但是因为我切换了它,所以我不能输入任何东西。

【问题讨论】:

  • @Cdhippen 你能发布marked() 函数吗?
  • 当您控制台记录handleKeyUp 中的event.target.value 时会发生什么?
  • 删除文本区的value={this.state.value}就可以了

标签: javascript html reactjs onkeyup


【解决方案1】:

我只想从 textarea 中删除 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')
);

【讨论】:

  • 如果我们需要控制那个值怎么办?
  • 啊,在这种情况下,您需要使用“受控组件”@TanDat。看看这个:reactjs.org/docs/forms.html
  • 但是你不能使用onKeyUp来处理Enter键?
【解决方案2】:

由于事件发生在文本框的实际值更改之前,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>

【讨论】:

  • 您可以识别按键,如果是退格键,则删除最后一个字符。但是,您必须为每个特殊键(例如箭头)和组合键执行此操作。这就是为什么它是一个挑战。在现实世界中,您应该使用onChange
  • 我遇到了,是的。即使我让 onKeyUp 开始工作,挑战仍然失败,所以我不确定到底应该发生什么。我将为他们创建一个论坛帖子并询问发生了什么
  • 您应该尝试其他答案 - 不受控制的组件,或使用 ref 更新。可能更适合您的需求。
  • 使用 ref 实际上效果更好,没有捕获特殊字符
  • 或者监听keyup事件的keyCode,根据那个keyCode有条件的清除状态。这真的取决于挑战的确切内容......
【解决方案3】:

您可以通过不给它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>
    );
  }
}

【讨论】:

  • 这里使用 ref 有什么好处?
  • 虽然测试仍然失败,但效果很好(虽然比 onChange 慢),所以我需要给那里的论坛发消息,看看发生了什么。我也很好奇,ref 到底在这里做什么?
  • @Cdhippen 似乎没有必要使用ref。只需从您问题中的代码中删除 value={this.state.value} 即可。我不知道onKeyUp 事件是这样工作的。
【解决方案4】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-23
    • 2021-09-15
    • 1970-01-01
    相关资源
    最近更新 更多