React onChange 未在受控 select 字段上触发
React onChange not fired on controlled select field
以下代码看似正确,但未按预期工作。
import React, {useEffect, useState} from "react"
import ReactDOM from "react-dom"
const Page = (props) => {
const [selectedValue, setSelectedValue] = useState(0)
const handleChange = () => {
console.log(1)
}
useEffect(() => {
setTimeout(() => {
setSelectedValue(2)
}, 1500)
}, [])
return (
<div>
<select onChange={handleChange} value={selectedValue}>
<option value="1">1</option>
<option value="2">2</option>
</select>
</div>
)
}
ReactDOM.render(
<Page />,
document.getElementById('pageRoot')
)
因此,当页面在 1.5 秒后加载时,它会选择第二个选项,但不会触发 onChange,因为控制台中没有任何记录。
我猜是因为当元素失去焦点时会发生 onchange,因此在以编程方式更改此元素时,焦点永远不会发生。
以编程方式设置状态不能触发 onChange
处理程序,否则我们会发现自己处于以下组件的无限循环中:
const Page = (props) => {
const [selectedValue, setSelectedValue] = useState(0)
const handleChange = (e) => {
setSelectedValue(e.target.value)
console.log(1)
}
useEffect(() => {
setTimeout(() => {
setSelectedValue(2)
}, 1500)
}, [])
return (
<div>
<select onChange={handleChange} value={selectedValue}>
<option value="1">1</option>
<option value="2">2</option>
</select>
</div>
)
}
handleChange
触发 setSelectedValue
,触发 handleChange
,触发 setSelectedValue
...
所以是的,以编程方式设置状态不会触发 onChange
处理程序是预期的行为。
但是,您可以确保始终通过代理,具体取决于您想要实现的目标:
const Page = (props) => {
const [selectedValue, setSelectedValue] = useState(0)
const handleChange = (newValue) => {
setSelectedValue(newValue)
console.log(1)
}
useEffect(() => {
setTimeout(() => {
handleChange(2)
}, 1500)
}, [])
return (
<div>
<select onChange={(e) => handleChange(e.target.value)} value={selectedValue}>
<option value="1">1</option>
<option value="2">2</option>
</select>
</div>
)
}
以下代码看似正确,但未按预期工作。
import React, {useEffect, useState} from "react"
import ReactDOM from "react-dom"
const Page = (props) => {
const [selectedValue, setSelectedValue] = useState(0)
const handleChange = () => {
console.log(1)
}
useEffect(() => {
setTimeout(() => {
setSelectedValue(2)
}, 1500)
}, [])
return (
<div>
<select onChange={handleChange} value={selectedValue}>
<option value="1">1</option>
<option value="2">2</option>
</select>
</div>
)
}
ReactDOM.render(
<Page />,
document.getElementById('pageRoot')
)
因此,当页面在 1.5 秒后加载时,它会选择第二个选项,但不会触发 onChange,因为控制台中没有任何记录。
我猜是因为当元素失去焦点时会发生 onchange,因此在以编程方式更改此元素时,焦点永远不会发生。
以编程方式设置状态不能触发 onChange
处理程序,否则我们会发现自己处于以下组件的无限循环中:
const Page = (props) => {
const [selectedValue, setSelectedValue] = useState(0)
const handleChange = (e) => {
setSelectedValue(e.target.value)
console.log(1)
}
useEffect(() => {
setTimeout(() => {
setSelectedValue(2)
}, 1500)
}, [])
return (
<div>
<select onChange={handleChange} value={selectedValue}>
<option value="1">1</option>
<option value="2">2</option>
</select>
</div>
)
}
handleChange
触发 setSelectedValue
,触发 handleChange
,触发 setSelectedValue
...
所以是的,以编程方式设置状态不会触发 onChange
处理程序是预期的行为。
但是,您可以确保始终通过代理,具体取决于您想要实现的目标:
const Page = (props) => {
const [selectedValue, setSelectedValue] = useState(0)
const handleChange = (newValue) => {
setSelectedValue(newValue)
console.log(1)
}
useEffect(() => {
setTimeout(() => {
handleChange(2)
}, 1500)
}, [])
return (
<div>
<select onChange={(e) => handleChange(e.target.value)} value={selectedValue}>
<option value="1">1</option>
<option value="2">2</option>
</select>
</div>
)
}