مرحبًا ، أستخدم وضع التحكم في الإدخال واشترك في حدث 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
في مثالك) ، ينتج عن ذلك عدم ظهور حرف المسافة مطلقًا.
هذا يبدو لي وكأنه خطأ في الطريقة التي يتفاعل بها هذان الحدثان.
cctrueadmgaearon لخبرتهم في نظام الأحداث
مرحبًا ، أنا جديد هنا ، أحاول تعلم هندسة React.
bvaughn هذا شيء وجدته حول المشكلة.
onKeyDown
event لا يحظر onChange
بدلاً من أن يتم تشغيله قبل تعديل الإدخال. بشكل أساسي ، ينتقل onKeyDown
قبل onChange
لأن إدخال النص يحدث في onKeyUp
.
في هذه الحالة بالذات ، تكمن المشكلة في أنه في حدود keyDown
، عندما يكون setCode
مكالمات ، في أول dispatchAction
_Fiber_ memoizedState
بدون الحرف الجديد (من الواضح) و e
التي ستتم إضافتها. في النهاية ، يضيف الحرف الجديد إلى المدخلات. ثم يقوم useEffect()
بتشغيل dispatchAction
مرة أخرى داخل _ نفس قائمة الانتظار_ (لست متأكدًا مما إذا كانت قائمة الانتظار) ولكنها لا تعرف أي شيء عن الدعائم المحدثة. نتيجة لذلك ، عندما يكون commitRoot
، فإنه يستعيد pendingProps
وهو نفسه كما كان في memoizedState
. باختصار ، تتم إضافة الحرف (مسافة في هذا المثال) ثم يتم استعادة الحالة القديمة على الفور بدون الحرف الجديد (مسافة) ، لذلك يبدو أنه لا يضيف أي شيء.
كمثال على عدم استخدام _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])
وسيعمل.
آمل أنه من المنطقي.
ركضت في نفس المشكلة ، وقمت بإصلاح استدعاء setState الخاص بي في aa setTimeout في معالج keydown.
لدي فضول لمعرفة ما إذا كان هذا شيء يجب أن يعمل بشكل مختلف تحت غطاء المحرك في React أو إذا كان هذا الخطأ يشير إلى خطأ أكبر أو نمط سيئ من جانب المطور؟