我已经学习了2个星期的React,现在我正试图弄清楚Lifting State Up的工作原理。在这段代码中,我试图做一个简单的计数器,单击“递减”或“递增”按钮,然后使用称为handleButtons的函数更新状态。我正在主文件“ App.js”中处理状态对象,因为这样我就可以根据需要使用任意数量的“ Counter”组件,它们共享相同的状态,因此我可以用一个按钮更新所有Counters。我使用'componentWillMount'函数创建了'Counter'组件数组并将其显示在渲染函数中。问题是,当我单击这些按钮之一时,什么也没有发生。状态已更新(我可以在控制台上看到它),但是计数器组件在网页上仍然显示为“ 0”。
这是我的App.js文件
import React from 'react';
import './App.css';
import {Counter} from './components/Counter';
class App extends React.Component{
state = {
count: 0
}
counters = []
handleButtons = (event) => {
if(event.target.name === 'increment'){
this.setState({
count: this.state.count + 1
})
}else if(event.target.name === 'decrement'){
this.setState({
count: this.state.count - 1
})
}
console.log(this.state.count)
}
componentWillMount(){
for(let i = 0; i< 10;i++){
this.counters.push(<div key = {i}><Counter count = {this.state.count}/><br/></div>)
}
}
render(){
return(
<div className = 'App'>
{this.counters}
<button className = 'Button' name = 'increment' onClick = {this.handleButtons}>Increment</button><br/><br/>
<button className = 'Button' name = 'decrement' onClick = {this.handleButtons}>Decrement</button>
</div>
);
}
}
export default App;
这是我的Counter.js文件
import React from 'react';
export class Counter extends React.Component{
render(){
return(
<div className = 'App'>
{this.props.count}
</div>
)
}
}
我希望这些组件增加其值,但它们确实增加了,但不会在浏览器上刷新
答案 0 :(得分:0)
好吧,这段代码有很多错误。让我们开始简单,React组件导入:
componentWillMount(){
for(let i = 0; i< 10;i++){
this.counters.push(<div key = {i}><Counter count = {this.state.count}/><br/></div>)
}
}
这是错误的,您不必使用这样的组件(可以,但不是必须使用的组件),该组件在render函数中的使用方式如下:
render(){
return(
<div className = 'App'>
<Counter count={this.state.count} /> //this line right here is the important
<button className = 'Button' name = 'increment' onClick = {this.handleButtons}>Increment</button><br/><br/>
<button className = 'Button' name = 'decrement' onClick = {this.handleButtons}>Decrement</button>
</div>
);
}
请注意,我们删除了您拥有的那个奇怪的数组,并使用了导入的Counter组件,还要注意,在此状态下,我们添加了一个与counter相等的属性(在jsx中为prop)。
每次更改(更改,更新)状态时,都会执行render函数,并重新渲染元素,因此,现在,每次使用setState()更新状态时,都会使用新值来呈现计数器。
我的建议是,删除整个componentWillMount(),因为它现在没有用了,还删除了父类的counters = []属性。
还请注意,只有在创建组件时ComponentWillMount()才能使用,如果您要使用这种方式,则必须使用每次更改状态时执行的 ComponentDidUpdate()。
答案 1 :(得分:0)
componentWillMount
不适合您的情况。
您可以使用arrow
函数进行显示。
// prepare counters items to render
renderCounters = () => {
const { count } = this.state;
let counters = [];
for(let i = 0; i< 10;i++){
counters.push(<div key = {i}><Counter count={count}/></div>);
}
return counters;
}
...
// render function
render(){
return(
<div className = 'App'>
{this.renderCounters()}
<button className = 'Button' name = 'increment' onClick = {this.handleButtons}>Increment</button><br/><br/>
<button className = 'Button' name = 'decrement' onClick = {this.handleButtons}>Decrement</button>
</div>
);
}
以某种方式更改状态值时,组件将自动重新呈现。
这意味着将调用render
函数。
您无需担心要准备在render
函数中显示的组件。但是,您仅不应在setState
函数中调用render
。
如果有要渲染的数组,则可以在map
函数或arrow
函数中直接使用render
函数。
假设您有一个数组显示为“ myCounters”,
// render function
render(){
const { myCounters } = this.state;
return(
<div className = 'App'>
{myCounters.map((item, index) =>
<div key = {index}>
<Counter count={item.count}/>
</div>)
}
<button className = 'Button' name = 'increment' onClick = {this.handleButtons}>Increment</button><br/><br/>
<button className = 'Button' name = 'decrement' onClick = {this.handleButtons}>Decrement</button>
</div>
);
}
答案 2 :(得分:0)
我真的很喜欢这个问题,因为您实际上偶然发现了一个直到现在我还没有想到的极端情况。
基本上,这是因为您正在将组件添加到不在componentWillMount函数状态下的列表中。实际上,这些“ Counter”组件不会被更新,也不会从组件生命周期中删除。
所有您需要做的,请确保将这些计数器添加到生命周期中。为此,您可以定义一个列表并将其映射到渲染函数中。看这里: Rendering an array.map() in React
希望有帮助!
答案 3 :(得分:0)
我已经看到了一些答案,但是在您开始使用React的同时,我也想详细说明问题并添加其他答案。了解问题是学习的第一步,也是最重要的一步:
问题:
您正在使用生命周期方法componentWillMount
,该方法在安装时即开始运行时运行,并使用循环生成计数器数组。现在,您的计数器列表具有状态依赖性,该状态依赖性在生命周期方法中仅使用初始值0
进行了一次解析。为什么? componentWillMount
设计为只能运行一次,因此,当您的状态更新时,它不会影响componentWillMount
或Counter
列表输入中的任何内容。这就是为什么需要渲染的任何内容都应该在render函数中或从render函数调用而不与生命周期方法链接的原因。
解决方案:
您无需在componentWillMount
中生成它。它可以简单地在render
方法中进行处理,并且由于您将在render方法中定义state
依赖关系,因此React将确保无论何时更新状态,您的Counters列表都会得到更新。>
话多了,给我看看代码:
下面的代码段将是您的新渲染功能,并且您可以安全地删除componentWillMount
,尽管您可以生成多种样式的列表,但我在这里发挥了主导作用。
render() {
let counterList = [];
for (let i = 0; i < 10; i++) {
counterList.push(
<div key={i}>
<Counter count={this.state.count} />
<br />
</div>
);
}
return (
<div className="App">
{counterList}
<button
className="Button"
name="increment"
onClick={this.handleButtons}
>
Increment
</button>
<br />
<br />
<button
className="Button"
name="decrement"
onClick={this.handleButtons}
>
Decrement
</button>
</div>
);
}
}
另外,React已将componentWillMount
声明为不安全,还有更多不使用它的原因,如果您认为确实需要它,请使用构造函数。
请咨询docs。