React父组件状态变更后,子组件为何未重新渲染获取新值?
问题解答
- 可以让子组件渲染新值,只需修正子组件的实现逻辑即可。
- 错误原因:
- 子组件
Grid仅在初始化的constructor中,将父组件传入的props.childName赋值给自身state,但constructor只会执行一次。 - 当父组件更新
name并传递新的childName给子组件时,子组件的state不会自动同步新的props值,且子组件渲染依赖的是自身旧的state而非最新props。
- 子组件
修正方案
方案一:子组件直接使用Props(推荐)
子组件无需维护自身state,直接读取props的值,父组件props更新时,子组件会自动重新渲染。
修改后的Grid组件:
import * as React from 'react'; interface PropsParams { childName: string; } export class Grid extends React.Component<PropsParams, {}> { render() { // 直接使用props中的值,不再依赖state const { childName } = this.props; let mainChildOutput = <span>{childName}</span>; return ( <div> <div>### Child ####</div> <strong>Name</strong>: {mainChildOutput} </div> ); } }
方案二:监听Props变化更新State(仅当子组件必须维护State时使用)
如果子组件需要将props存入自身state,需通过componentDidUpdate生命周期监听props变化,主动更新state:
修改后的Grid组件:
import * as React from 'react'; interface PropsParams { childName: string; } export class Grid extends React.Component<PropsParams, {}> { state: any = {}; constructor(props: PropsParams) { super(props); this.state = { childName: this.props.childName }; console.log(`CHILD -> this.state.name : ${this.state.childName}`); } // 监听props变化,同步更新state componentDidUpdate(prevProps: PropsParams) { if (prevProps.childName !== this.props.childName) { this.setState({ childName: this.props.childName }); console.log(`CHILD -> updated state.name : ${this.props.childName}`); } } render() { const { childName } = this.state; let mainChildOutput = <span>{childName}</span>; return ( <div> <div>### Child ####</div> <strong>Name</strong>: {mainChildOutput} </div> ); } }
父组件优化建议
父组件中存在两处不规范写法,建议同步修正:
- 初始化State的正确方式:不要直接修改
this.state属性,应在constructor中直接赋值完整的state对象。 - 使用受控组件获取输入值:避免直接操作DOM,通过React的受控组件机制管理输入框值。
修改后的DataLoader组件:
import * as React from 'react'; import { Grid } from './Grid.tsx'; interface LoaderProps { name: string; } export class DataLoader extends React.Component<LoaderProps, {}> { constructor(props: LoaderProps) { super(props); // 正确初始化state this.state = { name: this.props.name, inputValue: this.props.name }; this.changeName = this.changeName.bind(this); this.handleInputChange = this.handleInputChange.bind(this); } // 受控组件的输入变化处理 handleInputChange(e: React.ChangeEvent<HTMLInputElement>) { this.setState({ inputValue: e.target.value }); } changeName() { // 从state获取输入值,无需操作DOM this.setState({ name: this.state.inputValue }); } render() { const { name, inputValue } = this.state; let parentOutput = <span>{name}</span>; return ( <div> <button onClick={this.changeName}>Change Name</button> {/* 受控组件绑定value和onChange */} <input id="mapvalue" type="text" placeholder="name" value={inputValue} onChange={this.handleInputChange} /> <hr id="parent" /> <div>### Parent ###</div> <strong>Name</strong>: {parentOutput} <hr id="child" /> <Grid childName={name} /> </div> ); } }
内容的提问来源于stack exchange,提问作者raddevus
相关产品推荐
相关产品推荐

