onKeyUp 不能在 onChange 的 React 中工作

Posted

技术标签:

【中文标题】onKeyUp 不能在 onChange 的 React 中工作【英文标题】:onKeyUp not working in React where onChange did 【发布时间】: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() 函数吗? 标记为js库:marked.js.org/#/README.md#README.md 当您控制台记录handleKeyUp 中的event.target.value 时会发生什么? 删除文本区的value=this.state.value就可以了 【参考方案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 道具,它应该可以工作。

【讨论】:

以上是关于onKeyUp 不能在 onChange 的 React 中工作的主要内容,如果未能解决你的问题,请参考以下文章

请帮我解决为啥不能进入onchange事件

监听input变化的事件

Knockout js表编辑列获取onkeyup / Onchange最新值。 [小提琴](https://jsfiddle.net/chiks/975ncawv/521/)

当用js动态的改变一个输入框中的值后,并不能触发它的onchange事件why?

实时监听输入框

textarea 动态填充内容 文本框高度自适应