繁体   English   中英

道具更改时重新渲染React组件?

[英]Rerender React component when props change?

我有一个Mobx商店的react组件,看起来像这样:

class Board extends Component {
  componentDidMount() {
    this.props.dataStore.getSinglePlayer(1)
    this.props.squareStore.getAllSquares()
  }

  componentWillReceiveProps(nextProps) {
    if (
      this.props.dataStore.currentPlayer !==
      this.nextProps.dataStore.currentPlayer
    ) {
      this.nextProps.dataStore.getSinglePlayer(1)
    }
  }

  randomNumber() {
    return Math.floor(Math.random() * 6) + 1
  }

  roll(playerId, playerPosition) {
    let dice1 = this.randomNumber()
    let dice2 = this.randomNumber()

    let totalRoll = dice1 + dice2
    let totalPosition = totalRoll + playerPosition
    this.props.dataStore.changeUserPosition(playerId, totalRoll)
    document.getElementById('dice').innerHTML =
      'You rolled ' + totalRoll + '!  You are now on ' + totalPosition
  }

  render() {
    var player = {
      name: '',
      id: '',
      position: 0
    }
    console.log(this.props.dataStore.currentPlayer)
    if (this.props.dataStore.currentPlayer) {
      var currentPlayer = this.props.dataStore.currentPlayer
      player = {
        name: currentPlayer.name,
        id: currentPlayer.id,
        position: currentPlayer.position
      }
    }
    if (this.props.squareStore.squares) {
      var squares = this.props.squareStore.squares.map((square, i) => {
        var movement

        if (i == player.position) {
          movement = **
        }
        return (
          <li key={i}>
            <span>
              {square.title}
              <br />
              {movement}
              {square.price}
            </span>
          </li>
        )
      })
    } else {
      squares = <h4>Squares being loaded...</h4>
    }

    return (
      <div>
        <h1>Player: {player.name}</h1>
        <h2>Roll Dice!</h2>
        <button onClick={() => this.roll(player.id, player.position)}>
          Roll
        </button>{' '}
        <h1 id="dice">{}</h1>
        <div className="board">
          <ul>{squares}</ul>
        </div>
      </div>
    )
  }
}

export default inject('dataStore', 'squareStore')(observer(Board))

单击按钮后,此.props.dataStore.currentPlayer.position将更新为新值。 但是,只有在手动刷新页面时才会显示此新值。 有没有办法告诉组件值已更改,并且应该自动重新呈现?

React.Component生命周期=>更新

更新可能是由于道具或状态的更改引起的。

这意味着如果您想重新渲染组件,则需要:

  • 使用this.setState({ })方法更新组件状态
  • 或将更新的props从父级传递到该组件
  • 或者如果您将Redux/MobX用作状态管理器,则需要更新商店,以便连接的props将被更新并触发re-render

您应该考虑使用state以便setState重新呈现组件。 我建议重构您的代码,尤其是您的render 我认为您的播放器应该是状态,因为每次单击都会改变某些参数(当前播放器ID,名称和位置)。请注意不要直接在render设置您的状态,因为这可能会导致无限循环,并且render应始终使用纯方法。 因此,这需要更严肃的重构。 而且,通常不需要使用没有状态甚至没有构造函数的有状态组件!

无论如何,我们只需要setState totalPosition,它可以为您工作,但是您应该考虑优化组件。

class Board extends Component {
constructor(props){
 super(props);
 this.state = {
 totalPosition: null
 }
}
  componentDidMount() {
    this.props.dataStore.getSinglePlayer(1)
    this.props.squareStore.getAllSquares()
  }

  componentWillReceiveProps(nextProps) {
    if (
      this.props.dataStore.currentPlayer !==
      this.nextProps.dataStore.currentPlayer
    ) {
      this.nextProps.dataStore.getSinglePlayer(1)
    }
  }

  randomNumber() {
    return Math.floor(Math.random() * 6) + 1
  }

  roll(playerId, playerPosition) {
    let dice1 = this.randomNumber()
    let dice2 = this.randomNumber()
    let totalRoll = dice1 + dice2
    this.setState({
      totalPostion: totalRoll + playerPosition
    });
    let totalPosition = totalRoll + playerPosition
    this.props.dataStore.changeUserPosition(playerId, totalRoll)
    document.getElementById('dice').innerHTML =
      'You rolled ' + totalRoll + '!  You are now on ' + this.state.playerPostion
  }

  render() {
    var player = {
      name: '',
      id: '',
      position: 0
    }
    console.log(this.props.dataStore.currentPlayer)
    if (this.props.dataStore.currentPlayer) {
      var currentPlayer = this.props.dataStore.currentPlayer
      player = {
        name: currentPlayer.name,
        id: currentPlayer.id,
        position: currentPlayer.position
      }
    }
    if (this.props.squareStore.squares) {
      var squares = this.props.squareStore.squares.map((square, i) => {
        var movement

        if (i == player.position) {
          movement = **
        }
        return (
          <li key={i}>
            <span>
              {square.title}
              <br />
              {movement}
              {square.price}
            </span>
          </li>
        )
      })
    } else {
      squares = <h4>Squares being loaded...</h4>
    }

    return (
      <div>
        <h1>Player: {player.name}</h1>
        <h2>Roll Dice!</h2>
        <button onClick={() => this.roll(player.id, player.position)}>
          Roll
        </button>{' '}
        <h1 id="dice">{}</h1>
        <div className="board">
          <ul>{squares}</ul>
        </div>
      </div>
    )
  }
}

export default inject('dataStore', 'squareStore')(observer(Board))
<button onClick={() => this.roll(player.id, player.position); this.forceUpdate()}>

我相信您并没有正确设置此互动。 我没有使用过MobX,但是反应的方法是改变道具。 如果您周围有一个包装组件,该组件正在监听商店中的更改,并将数据传递给Board,则它将自动更新。 我认为这个MobX connect软件包将对您非常有用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM