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 中工作的主要内容,如果未能解决你的问题,请参考以下文章
Knockout js表编辑列获取onkeyup / Onchange最新值。 [小提琴](https://jsfiddle.net/chiks/975ncawv/521/)