【发布时间】:2020-06-20 14:28:50
【问题描述】:
我正在处理一个表单,其中包含日历条目(日期和时间)等字段。代码如下:
{dates.map((d, i) => (
<div className="date-time-entry" key={i}>
<div className="date-picker">
<DatePicker
selected={new Date(d.startDate)}
dateFormat="dd MMM yyyy"
onChange={date => {
const newDates = [...dates]
newDates[i].startDate = date
setDates(newDates)
}}
/>
to
<DatePicker
selected={new Date(d.endDate)}
dateFormat="dd MMM yyyy"
onChange={date => {
const newDates = [...dates]
newDates[i].endDate = date
setDates(newDates)
}}
/>
{i ? (
<span
onClick={() => {
const newDates = dates.filter((d, k) => k !== i)
setDates(newDates)
}}
>
<FontAwesomeIcon icon={faTimes} />
</span>
) : null}
</div>
{dates[i].times.map((t, j) => {
return (
<div className="time-picker" key={j}>
at
<input
ref={(input) => { nameInput = input }}
value={t.start}
onChange={e => {
const newDates = [...dates]
newDates[i].times[j].start = e.target.value
setDates(newDates)
}}
/>{' '}
to{' '}
<input
ref={(input) => { nameInput = input }}
value={t.end}
onChange={e => {
const newDates = [...dates]
newDates[i].times[j].end = e.target.value
setDates(newDates)
}}
/>
<span
onClick={() => {
const newTimes = dates[i].times.filter((t, k) => k !== j)
const newDates = [...dates]
newDates[i].times = newTimes
setDates(newDates)
}}
>
<FontAwesomeIcon icon={faTimes} />
</span>
</div>
)
})}
<div
className="add-time"
onClick={() => {
const newDates = [...dates]
newDates[i].times = [
...newDates[i].times,
{ start: '12:00', end: '13:00' }
]
setDates(newDates)
}}
>
Add Time
</div>
</div>
)
)}
然后有useState()钩子定义为:
const [dates, setDates] = useState([
{
startDate: new Date(),
endDate: new Date(),
times: [{ start: '12:00', end: '13:00' }]
}
])
我遇到的问题是,无论何时调用 onChange - 每次击键都会发生重新渲染并且我的组件失去焦点。
我尝试使用onBlur 和defaultValue 代替onChange,但也存在焦点问题 - 需要单击两次才能切换焦点,因为第一次被重新渲染消耗。
我也尝试过添加超时来处理onBlur“输”的一键点击如下:
<input
defaultValue={t.start}
onBlur={e => {
const value = e.target.value
timeout = setTimeout(() => {
const newDates = [...dates]
newDates[i].times[j].start = value
setDates(newDates)
}, 0)
}}
onFocus={() => {
clearTimeout(timeout)
}}
/>
最后一个版本不再失去焦点,而是失去状态更新。关于如何更好地处理这个问题,或者甚至修复我现有的代码的任何建议?
【问题讨论】:
-
这只是一个提示,但我很确定问题出在更改键上。当密钥更改时,组件不会在同一个实例上更新,而是卸载并安装一个新实例。这也涉及到 DOM 对象,这将明确焦点。所以这可能不是答案,但它是一个常见的原因。
标签: reactjs dom-events react-state rerender react-effects