React中State Hook与局部变量赋值的区别是什么?
React局部变量赋值后组件不渲染的问题解析
问题场景
我习惯使用C#这类基于类的面向对象语言,通常可以将对象赋值给局部变量供后续使用,但在React示例中这么做却出现了问题:点击按钮后handleClick函数里打印tempPersonObj能拿到目标对象,可PersonDetails组件里打印的却是空对象,组件也无法正确渲染详情内容。
用户提供的代码如下:
import React, {useState} from "react"; const persons = [ { "name": "Arto Hellas", "number": "040-123456", "count": 3, "id": 1 }, { "name": "Ada Lovelace", "number": "39-44-5323523", "count": 10, "id": 2 }, { "name": "Mary Poppendieck", "number": "39-23-6423122", "count": 17, "id": 3 } ] const PersonDetails = ({person}) => { console.log(person) return ( <div> <p>-----------------</p> <p>{person.name}</p> <p>{person.number}</p> <p>{person.count}</p> </div> ) } const App = () => { const [view, setView] = useState(false) const [personObj, setPersonObj] = useState({}) let tempPersonObj = {}; const handleClick = (person) => { //此方式可行 // setPersonObj(person) //此方式不可行 tempPersonObj = person console.log(tempPersonObj) setView(true) } return ( <div> <h1>List:</h1> {persons.map((person) => { return ( <div key={person.id}> {person.name} {""} <button onClick={() => handleClick(person)}>View</button> </div> )}) } {/* 此方式可行 */} {/* {view && <PersonDetails person={tempPersonObj}/>} */} {/* 此方式不可行 */} {view && <PersonDetails person={personObj}/>} </div> ); } export default App
核心原因:React的渲染机制
- React函数组件的重新渲染仅依赖于状态(state)或属性(props)的变化,普通局部变量(比如
tempPersonObj)不属于React的状态管理体系,修改这类变量不会触发组件更新。 - 你在
handleClick里看到tempPersonObj有值,是因为那是当前函数执行上下文里的变量值,但组件重新渲染时会重新执行整个App函数,此时tempPersonObj会被重新初始化为{},所以子组件拿到的是空对象。 - 用
setPersonObj(person)的方式可行,是因为调用状态更新函数会通知React状态发生改变,触发组件重新渲染,此时personObj会持有新值并传递给子组件。
正确实现方式
直接使用React状态管理选中的用户对象,无需额外的普通局部变量,同时可以合并冗余的状态逻辑:
import React, {useState} from "react"; const persons = [ { "name": "Arto Hellas", "number": "040-123456", "count": 3, "id": 1 }, { "name": "Ada Lovelace", "number": "39-44-5323523", "count": 10, "id": 2 }, { "name": "Mary Poppendieck", "number": "39-23-6423122", "count": 17, "id": 3 } ] const PersonDetails = ({person}) => { console.log(person) return ( <div> <p>-----------------</p> <p>{person.name}</p> <p>{person.number}</p> <p>{person.count}</p> </div> ) } const App = () => { // 用单个状态管理选中的用户,初始值设为null const [selectedPerson, setSelectedPerson] = useState(null); const handleClick = (person) => { setSelectedPerson(person); } return ( <div> <h1>List:</h1> {persons.map((person) => { return ( <div key={person.id}> {person.name} {""} <button onClick={() => handleClick(person)}>View</button> </div> )}) } // 当选中用户存在时,渲染详情组件 {selectedPerson && <PersonDetails person={selectedPerson}/>} </div> ); } export default App
关键总结
在React函数组件中,任何需要驱动视图更新的数据,都必须放在状态(如useState)或属性中,普通局部变量无法触发组件重新渲染,这是和C#这类传统OOP语言在UI更新逻辑上的核心差异。
内容的提问来源于stack exchange,提问作者Learning4Ever
相关产品推荐
相关产品推荐

