状态未在屏幕上更改和呈现

时间:2018-06-09 18:55:55

标签: reactjs

我正在尝试更改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>
      );
    }
  }

2 个答案:

答案 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

这里有几点需要注意:

  1. 状态由父this.state.items管理。

  2. 父级使用名为handleFancyClick的类方法来更新其状态。

  3. 父级定义子级将使用的prop键,在本例中为onFancyClick。这是一个回调。您可以看到它告诉孩子&#34;当您致电props.onFancyClick()时,我将使用您传递给我的任何数据执行我的this.handleFancyClick()

  4. 每当孩子准备好时,它会执行props.onFancyClick()来触发回调。

  5. 另请注意,在handleFancyClick内,我们无可置疑地替换了this.state.items。这是更好地替换对象或数组时更好的做法,因为这样做会破坏内存中的引用并避免状态问题。请记住,React是单向的,因此事情会随着时间的推移而发生,并且为了避免在某个时间点出现错误,我们遵循严格的不变理念。

  6. 希望这会有所帮助。我写了一篇关于不可变函数式编程的大文章,如果你想了解更多关于JavaScript中的引用和垃圾收集的话,你可以阅读:https://medium.com/@agm1984/an-overview-of-functional-programming-in-javascript-and-react-part-one-10d75b509e9e

    研究我在这里展示的代码。当我第一次学习它时,我很难理解,因为它从父母到孩子以及回到父母的范围。我建议你写几次,直到你完全理解这种模式。你会经常使用它。