【问题标题】:How to update state according to received props in runtime in React Native?如何根据 React Native 运行时收到的 props 更新状态?
【发布时间】:2017-09-23 21:21:39
【问题描述】:

假设有 2 个 React Native 组件

是保持评级值(从 1 到 5)处于其状态的容器。

是一个组件,它根据收到的道具“评级”或根据点击的星星来渲染星星图像。

看起来像这样:

class Parent extends Component {

  constructor(props) {
    super(props);
    this.state = {
      rating:5
    }
  }

  render() {
    return (
      <StarRating rating={this.state.rating}></StarRating>
    )
  }
}

class StarRating extends Component {

  _generateStars(rating) { ... }; //return an array with JSX rect components 
                                  //according to "rating" prop (e.g. 1,2..5). 
                                  //Each component is the star image...

  render() {

  stars = this._generateStars(this.props.rating); // *

    return (
      <View>
        {stars}
      </View>
    )
  }
}

如果 收到新的道具“评级”,它的渲染函数会自动调用新道具并且一切正常,我们会看到更新的星星图像。

包裹到 元素的每颗星以及 我应该怎么做 如果我点击某个星并且 应该用新的星数重新渲染自身。在这种情况下,我不能直接在 中更改“this.props.rating”(参见上面的 *)。我想我必须在 中使用 setState() 但是 如何理解 Render 应该采用哪种方式...根据新状态或新收到的道具?我的意思是如何在渲染功能中确定是收到新道具还是点击生成?

看起来 应该有两种方法来更新自己的星星:

  1. 通过父级的新道具。

  2. 通过点击自身内部的星星。

在这种情况下应该采取什么方法?

谢谢。

【问题讨论】:

标签: reactjs react-native


【解决方案1】:

我会让StarRating 管理这个状态,但你的方法也是可行的,具体取决于具体情况。

您可以通过您的父级传递updateRating 函数,然后您可以从 StarRating 控制评级,而无需将状态移动到其中。

class Parent extends Component {
  constructor(props) {
    super(props);
    this.state = {
      rating:5
    }
  }

  render() {
    return (
      <StarRating rating={this.state.rating} 
        updateRating={(rating) => this.setState({rating})} 
        />
    )
  }
}

class StarRating extends Component {

  _generateStars(rating, updateRating) {
      // Generate stars with custom onPress
      // <Star onPress={() => updateRating(starIndex)} />
  }

  render() {

  stars = this._generateStars(this.props.rating, this.props.updateRating); // *

    return (
      <View>
        {stars}
      </View>
    )
  }
}

【讨论】:

  • 是否有可能做同样的功能,但没有两次调用 Render()(在 Parent (setState...) 中调用一次,在 StarRating 中再调用一次(由于收到新道具))?我的意思是,如果用户单击星号,则仅 StarRating 调用 Render(),而不通过 setState({rating}) 在 Parent 中调用 Render()?谢谢。
  • 渲染周期还可以,我觉得不需要进一步优化。如果您真的想要,您可以将状态移动到 StarRating,但您将获得 0 的性能提升。不过有可能。
【解决方案2】:

我猜你困惑的是谁应该控制rating的状态(表示不同的星图)。

我认为父组件应该控制这个状态,因为子组件(StarRating)只是一个视图反映rating的状态,他并不关心这个状态是什么意思,谁应该关心这个状态的含义是他的父母(父母)。

另外,控制父级中的所有子级rating 状态便于将来扩展功能。

【讨论】:

  • 所以,伙计们,在这两种情况下,您的意思是点击事件的生命周期应该是: 1. 用户点击一颗星(星当然放在 StarRating 里面)。 2. StarRating 生成回调到父级,其中包含按下的星号的数据。 3. 父级根据回调数据“保存”其状态的星数。 4. Parent 用新的评分(星数)生成 setState,调用 Parent Render 函数。 5. StarRating 更新星号,收到新道具。
  • 这意味着 StarRating 是一个“愚蠢”的组件,它从来不知道自己的星数,所以它应该被另一个知道当前状态的组件包装?理解正确吗?
  • 第二条评论是正确的,StarRating 在某种程度上是一个“愚蠢”的组件,这种方式更好地利用了“道具”和“状态”的概念。而且我认为 StarRating 中没有必要将“TouchableOpacity”包裹起来,它可以存在于 Parent 中,StarRating 只是一个通过不同道具渲染星星图像的图像视图,他没有责任响应您的点击。谢谢!
  • 我的意思是将 StarRating 包装在 Parent 的 TouchableOpacity 中
  • 谢谢,但需要 StarRating 中的“TouchableOpacity”来确定按下的是哪颗星(第一、第二...)。
猜你喜欢
  • 2018-11-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-01
相关资源
最近更新 更多