setState -> 告诉React 状态变化 -> 需要重新渲染 -> 重新执行NameInput函数
javascript
import { useState } from "react";
function NameInput() {
const [name, setName] = useState("")
console.log(name)
const [agreed, setAgreed] = useState(false)
console.log(agreed)
return (
<>
<input value={name}
onChange={(e) => setName(e.target.value)}
/>
<input type="checkbox"
checked={agreed}
onChange={(e) => setAgreed(e.target.checked)}
/>
</>
)
}
export default NameInput
原理很简单:console.log(agreed) 写在组件函数体里,不是写在事件回调里。
React 组件本质就是一个函数,每次这个组件要重新渲染,React 就会重新调用这个函数一遍,函数体里的代码(包括 console.log)都会重新执行一次。
点击 checkbox 的流程是:
- 触发
onChange,调用setAgreed(e.target.checked) setAgreed是 state 更新函数,调用它会告诉 React:"这个组件的状态变了,需要重新渲染"- React 重新执行
NameInput()这个函数 - 函数体从头执行一遍,
console.log(agreed)也就跟着执行一遍,打印出最新的agreed值
所以你点一次 checkbox,setAgreed 触发一次重渲染,NameInput 函数体整体跑一遍,console.log 自然就打印一次。同理你打字改 name 的时候,console.log(name) 也会跟着打印,因为 setName 也会触发重渲染。
这也是为什么之前提到的 TodoApp 里那个 console.log 在 StrictMode 下刷新会打印 2 次的原因是一样的:只要函数体被调用,里面所有同步代码都会执行,不只是 return 的 JSX。