こんにちは、私は入力制御モードを使用し、 onKeyDown
およびonChange
イベントをサブスクライブします。 ユーザーがスペースに入るとエフェクトがトリガーされます。 ただし、スペースは画面に表示されません。 これはReactのバグですか、それとも私が使用している方法に何か問題がありますか? ただし、 onKeyUp
サブスクライブするのは正常です。 これは混乱しています。
Reactバージョン:16.13.1以前
コード例へのリンク:
import React, { useState,useEffect } from 'react'
const App = () => {
const [count, setCount] = useState(0)
const [value, setValue] = useState('')
const [code, setCode] = useState('add')
useEffect(() => {
if (code === 'add') {
setCount(c => c + 1)
} else {
setCount(c => c - 1)
}
}, [code, setCount])
const keyDown = e => {
if (e.keyCode === 32) {
console.log('space~')
if (code === 'add') {
setCode('minus')
} else {
setCode('add')
}
}
}
const handleChange = e => {
setValue(e.target.value)
}
return (
<div>
<div>{count}</div>
<br />
<input onKeyDown={keyDown} value={value} onChange={handleChange} />
</div>
)
}
export default App
入力要素がスペースを受け取ることができません
入力要素はスペースを受け取ることができます
onKeyDown
ハンドラーの状態更新がイベントを中断し、 onChange
ハンドラーが呼び出されないように見えます。 制御されたコンポーネントは、指示した内容(例ではvalue
状態)のみを表示するため、スペース文字は表示されません。
これは、これら2つのイベントが相互作用する方法で私にはバグのように見えます。
イベントシステムの専門知識を提供してくれたcc @ trueadm @gaearon
こんにちは、私はここで新しく、Reactアーキテクチャを学ぼうとしています。
@bvaughnこれが私が問題について見つけたものです。
onKeyDown
イベントは、入力が変更される前にトリガーされるのではなく、 onChange
ブロックしません。 基本的に、テキスト入力はonKeyUp
れるため、 onKeyDown
はonChange
よりも早くなります。
この特定のケースでは、問題は、 keyDown
で、 setCode
呼び出されたときに、最初のdispatchAction
_Fiber_に新しい文字がないmemoizedState
ことです(明らかに)追加されるe
。 最後に、入力に新しい文字を追加します。 次に、 useEffect()
は_同じキュー_内でdispatchAction
再度トリガーします(キューかどうかはわかりません)が、更新された小道具については何も知りません。 その結果、 commitRoot
場合、 memoizedState
と同じpendingProps
が復元されます。 つまり、文字(この例ではスペース)が追加された後、すぐに古い状態が新しい文字(スペース)なしで復元されるため、何も追加されていないように見えます。
_same queue_(?)を使用しない例として、この特定の例:
useEffect(() => {
if (code === 'add') {
setCount(c => c + 1)
} else {
setCount(c => c - 1)
}
}, [code, setCount])
次のように変更できます。
useEffect(() => {
if (code === 'add') {
setTimeout(() => setCount(c => c + 1), 0)
} else {
setTimeout(() => setCount(c => c - 1), 0)
}
}, [code, setCount])
そしてそれは動作します。
私はそれが理にかなっていることを願っています。
これと同じ問題が発生し、キーダウンハンドラーのsetTimeoutでsetState呼び出しをラップすると修正されました。
これがReactの内部で異なる動作をするはずなのか、それともこのエラーが開発者側のより大きな間違いや悪いパターンを示しているのか知りたいのですが。