我正在尝试更改PressButton类组件中的“currNum”的状态,并在Header类组件中呈现它,但我看不到这有效。这里是代码...我已经在App类中定义了状态,并尝试在PressButton类中更改它是允许的,如果不是,我该如何实现。
import React from 'react';
export default class App extends React.Component {
constructor(props){
super(props);
this.state={
score: 0,
prevNum: 1,
currNum: 0
}
};
render()
{
return(
<div>
<PressButtons currNum={this.state.currNum} prevNum={this.state.prevNum} prevScore={this.state.score}/>
<Header score={this.state.score} currNum={this.state.currNum}/>
</div>
);
}
}
class Header extends React.Component {
render(){
console.log('curnum in headert is '+this.props.currNum);
return(
<div>
<h1>Current Number:{this.props.currNum}</h1>
<h1>Current score: {this.props.score}</h1>
</div>
);
}
}
class PressButtons extends React.Component {
constructor(props){
super(props);
this.clickOne = this.clickOne.bind(this);
}
clickOne(e){
e.preventDefault();
const val = 1;
const prev = this.props.prevNum;
var prevScore= this.props.prevScore;
var currNum=this.props.currNum;
console.log(prev);
console.log(prevScore);
if(val === prev)
{
prevScore+=1;
}
this.setState(()=>{
return {
score: prevScore ,
currNum: 1,
prevNum: 1
};
});
console.log('curnum is '+currNum);
}
render(){
return(
<div>
<table>
<tr>
<td><button onClick={this.clickOne}>One</button></td>
<td><button>Two</button></td>
<td><button>Three</button></td>
</tr>
<tr>
<td><button>Four</button></td>
<td><button>Five</button></td>
<td><button>Six</button></td>
</tr>
<tr>
<td><button>Seven</button></td>
<td><button>Eight</button></td>
<td><button>Nine</button></td>
</tr>
</table>
</div>
);
}
}
答案 0 :(得分:0)
您使用setState()
作为 本地 PressButtons
,因此在调用clickOne()
时, 本地 PressButtons
状态更改,但App
状态不会更改。
因此,要更改应用状态,您应该Lifting State Up。这意味着将clickOne()
移动到App
类。因此,当clickOne()
被调用时,App
状态将被更改,Header
道具也会更改
答案 1 :(得分:0)
在React中,数据是单向流动的,这意味着一切都趋于从父到子,从上到下,从前到后(相对于时间)。
我们通常处理这种情况的方式是向子组件提供所有内容,并在控制行为的组件中维护状态,通常是父组件。
您感兴趣的部分是将数据更改提供给父级,您可以并且应该使用回调。当你使用回调时,孩子可以使用回调闭包来观察当时父母所需范围内的任何东西。
这样做的好处是可以让儿童部门免于关注其责任范围之外的细节。
我将为您绘制一个显示模式的简单示例,您可以将其应用于您的问题。
import React, { Component } from 'react'
class Parent extends Component {
constructor(props) {
super(props)
this.state = {
items: [
{ id: 1, content: 'hello' },
{ id: 2, content: 'world' },
],
}
}
handleFancyClick = (data) => {
console.log('CURRENT STATE', this.state.items)
console.log('DATA FROM CHILD', data)
const newItems = [...this.state.items, data]
console.log('NEW STATE', newItems)
this.setState({
items: newItems
})
}
render() {
return (
<div>
<h1>Happy Day! We got some YOLO data:</h1>
<hr />
<ul>
{this.state.items.map(item => (
<li key={item.id}>{item.content}</li>
))}
</ul>
<hr />
<Child
onFancyClick={this.handleFancyClick}
specialData={this.state.items}
/>
</div>
)
}
}
const Child = (props) => {
const currentListLength = props.specialData.length
return (
<button
onClick={() => props.onFancyClick({ id: (currentListLength + 1), content: 'that\'s rad' })}
style={{ cursor: 'pointer' }}
>
Hey I'm a stateless child, woot (also: {currentListLength})
</button>
)
}
export default Parent
这里有几点需要注意:
状态由父this.state.items
管理。
父级使用名为handleFancyClick
的类方法来更新其状态。
父级定义子级将使用的prop键,在本例中为onFancyClick
。这是一个回调。您可以看到它告诉孩子&#34;当您致电props.onFancyClick()
时,我将使用您传递给我的任何数据执行我的this.handleFancyClick()
。
每当孩子准备好时,它会执行props.onFancyClick()
来触发回调。
另请注意,在handleFancyClick
内,我们无可置疑地替换了this.state.items
。这是更好地替换对象或数组时更好的做法,因为这样做会破坏内存中的引用并避免状态问题。请记住,React是单向的,因此事情会随着时间的推移而发生,并且为了避免在某个时间点出现错误,我们遵循严格的不变理念。
希望这会有所帮助。我写了一篇关于不可变函数式编程的大文章,如果你想了解更多关于JavaScript中的引用和垃圾收集的话,你可以阅读:https://medium.com/@agm1984/an-overview-of-functional-programming-in-javascript-and-react-part-one-10d75b509e9e
研究我在这里展示的代码。当我第一次学习它时,我很难理解,因为它从父母到孩子以及回到父母的范围。我建议你写几次,直到你完全理解这种模式。你会经常使用它。