在受控选择字段上未触发反应onChange

时间:2019-07-30 18:59:21

标签: reactjs react-hooks

以下代码似乎正确,但无法正常工作。

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。

2 个答案:

答案 0 :(得分:1)

以编程方式设置状态不能触发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>
  )
}

答案 1 :(得分:0)

我猜测是因为在元素失去焦点时发生onchange,所以以编程方式更改焦点时,永远不会发生焦点。