Hallo, ich verwende den eingangsgesteuerten Modus und abonniere das Ereignis onKeyDown
und onChange
. Es wird ein Effekt ausgelöst, wenn der Benutzer Leerzeichen eingibt. Der Platz wird jedoch nicht auf dem Bildschirm angezeigt. Ist dies ein Fehler bei React oder stimmt etwas nicht mit der Art und Weise, wie ich es benutze? Aber onKeyUp
abonnieren ist normal. Das ist verwirrt.
Reaktionsversion: 16.13.1 und alt
Link zum Codebeispiel:
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
Das Eingabeelement kann das Leerzeichen nicht empfangen
Eingabeelement kann den Raum empfangen
Es sieht so aus, als ob die Statusaktualisierung im onKeyDown
-Handler das Ereignis unterbricht und verhindert, dass der onChange
-Handler aufgerufen wird. Da kontrollierte Komponenten nur das anzeigen, was Sie ihnen sagen (der Status value
in Ihrem Beispiel), wird das Leerzeichen nie angezeigt.
Das sieht für mich nach einem Fehler im Zusammenspiel dieser beiden Ereignisse aus.
cc @trueadm @gaearon für ihre Erfahrung mit Veranstaltungssystemen
Hallo, ich bin neu hier und versuche, die React-Architektur zu lernen.
@bvaughn Hier ist etwas, das ich über das Problem gefunden habe.
onKeyDown
Ereignis onChange
sondern wird früher ausgelöst, als die Eingabe geändert wird. Grundsätzlich geht onKeyDown
früher als onChange
da die Texteingabe in onKeyUp
.
In diesem speziellen Fall besteht das Problem darin, dass innerhalb von keyDown
, wenn setCode
anruft, beim ersten dispatchAction
_Fiber_ memoizedState
ohne das neue Zeichen (offensichtlich) vorhanden ist. und e
die hinzugefügt werden. Am Ende wird das neue Zeichen zur Eingabe hinzugefügt. Dann useEffect()
Trigger dispatchAction
wieder innerhalb der _same warteschlange_ (nicht sicher , ob es der Warteschlange) , aber es nicht zu aktualisierten Requisiten weiß nichts. Wenn es also commitRoot
, werden pendingProps
wiederhergestellt, die memoizedState
identisch sind. Kurz gesagt, das Zeichen (in diesem Beispiel Leerzeichen) wird hinzugefügt und der alte Zustand wird sofort ohne das neue Zeichen (Leerzeichen) wiederhergestellt, sodass es so aussieht, als würde nichts hinzugefügt.
Als Beispiel für die Nichtverwendung von _same queue_ (?) In diesem Beispiel:
useEffect(() => {
if (code === 'add') {
setCount(c => c + 1)
} else {
setCount(c => c - 1)
}
}, [code, setCount])
könnte geändert werden zu:
useEffect(() => {
if (code === 'add') {
setTimeout(() => setCount(c => c + 1), 0)
} else {
setTimeout(() => setCount(c => c - 1), 0)
}
}, [code, setCount])
und es wird funktionieren.
Ich hoffe es macht Sinn.
Das gleiche Problem ist aufgetreten, als ich meinen setState-Aufruf in aa setTimeout im Keydown-Handler eingeschlossen habe.
Ich bin gespannt, ob dies in React unter der Haube anders funktionieren sollte oder ob dieser Fehler auf einen größeren Fehler oder ein schlechtes Muster auf der Entwicklerseite hinweist.