React js不更新JSX数组

时间:2019-06-28 19:03:02

标签: javascript reactjs

我已经学习了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>
        )
    }
}

我希望这些组件增加其值,但它们确实增加了,但不会在浏览器上刷新

4 个答案:

答案 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设计为只能运行一次,因此,当您的状态更新时,它不会影响componentWillMountCounter列表输入中的任何内容。这就是为什么需要渲染的任何内容都应该在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>
    );
  }
}

See the working code here

另外,React已将componentWillMount声明为不安全,还有更多不使用它的原因,如果您认为确实需要它,请使用构造函数。

请咨询docs