React -状态改变的父不引起重新渲染子当传递作为道具?

  • 本文关键字:新渲染 改变 状态 React reactjs
  • 更新时间 :
  • 英文 :


我最近一直在尝试学习React,这个问题真的让我很困惑。下面是代码:

我已经创建了两个类组件:App,代表父类,Child,代表子类。

class App extends React.Component {
constructor() {
super()
this.state = {
myState: 0
}
this.handleClick = this.handleClick.bind(this)
}
handleClick() {
this.setState((previousState) => ({myState: previousState.myState + 1}), () => console.log(this.state.myState))
}
render() {
return (
<div>
<Child value={this.state.myState}/>
<button onClick={this.handleClick}>This updates the state of App (parent)</button>
</div>
)
}
}
class Child extends React.Component {
constructor(props) {
super(props)
this.state = {
value: this.props.value
}
this.randomize = this.randomize.bind(this)
}
randomize() {
this.setState({value: Math.random() * 100})
}
render() {
return(
<div>
<h1>My value is {this.state.value}</h1>
<button onClick={this.randomize}>This changes the state of Child</button>
</div>
)
}
}
ReactDOM.render(<App />, document.getElementById("root"));
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>

App组件包含一个按钮,每次点击它,它的状态值都会增加1。Child组件包含一个按钮,该按钮每次被点击时都会将其状态值更改为0到100之间的随机数。

在运行这个时,我希望每次myState在父改变时都重新渲染子,因为这是我传递给它的道具。我还希望Child中的this.state.value发生变化,因为我将其设置为myState。然而,当我增加myState时,Child完全不受影响,仍然显示randomize()之前给它的内容。

谁能告诉我怎么了?谢谢:)

Child构造函数中有以下代码片段:

this.state = {
value: this.props.value
}

上面的命令只在组件挂载之前设置一次Child状态。因此,任何递增/递减都不会从父级传递到子级。

解决这个问题的最好方法就是简单地将状态保存在父组件中,并且只传递一个可以更新它的函数。

试试这个:

class App extends React.Component {
constructor() {
super()
this.state = {
myState: 0
}
this.handleClick = this.handleClick.bind(this)
this.updateState = this.updateState.bind(this)
}
updateState(newState) {
this.setState(newState);
}

handleClick() {
this.setState((previousState) => ({myState: previousState.myState + 1}), () => console.log(this.state.myState))
}
render() {
return (
<div>
<Child value={this.state.myState} update={this.updateState}/>
<button onClick={this.handleClick}>This updates the state of App (parent)</button>
</div>
)
}
}
class Child extends React.Component {
constructor(props) {
super(props)
this.randomize = this.randomize.bind(this)
}
randomize() {
this.props.update({myState: Math.random() * 100})
}
render() {
return(
<div>
<h1>My value is {this.props.value}</h1>
<button onClick={this.randomize}>This changes the state of Child</button>
</div>
)
}
}
ReactDOM.render(<App />, document.getElementById("root"));
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>

您缺少component lifecycle。类的constructor只调用一次,而不是每次重新渲染。
如果u想要更改子节点的数据而不是父节点的数据,那么使用componentDidUpdate(),它将在数据更新时被调用。参见此处
修改后的子代码:

class App extends React.Component {
constructor() {
super()
this.state = {
myState: 0
}
this.handleClick = this.handleClick.bind(this)
}
handleClick() {
this.setState((previousState) => ({myState: previousState.myState + 1}), () => console.log(this.state.myState))
}
render() {
return (
<div>
<Child value={this.state.myState}/>
<button onClick={this.handleClick}>This updates the state of App (parent)</button>
</div>
)
}
}
class Child extends React.Component {
constructor(props) {
super(props)
this.state = {
value: this.props.value
}
this.randomize = this.randomize.bind(this)
}
randomize() {
this.setState({value: Math.random() * 100})
}
componentDidUpdate(prevProps, prevState) {
if (this.props.value !== prevProps.value) {
this.setState({value: this.props.value + prevState.value - prevProps.value})
}
}
render() {
return(
<div>
<h1>My value is {this.state.value}</h1>
<button onClick={this.randomize}>This changes the state of Child</button>
</div>
)
}
}
ReactDOM.render(<App />, document.getElementById("root"));
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>

最新更新