我可以在React.js中更新组件的道具吗?


217

在开始使用React.js之后,它似乎props是静态的(从父组件传入),而state基于事件的更改则似乎是静态的。但是,我在文档中注意到对的引用componentWillReceiveProps,其中具体包括以下示例:

componentWillReceiveProps: function(nextProps) {
  this.setState({
    likesIncreasing: nextProps.likeCount > this.props.likeCount
  });
}

这似乎意味着,性能可以改变根据的比较组件nextPropsthis.props。我想念什么?道具如何更改,或者我误认为道具的调用位置?

Answers:


249

除非组件是数组或对象,否则组件不能更新其自身的props(即使可能,组件也要更新其自己的props是反模式),但是可以更新其状态和其子级的props。

例如,仪表板speed处于其状态的字段,并将其传递给显示该速度的Gauge子级。它的render方法是公正的return <Gauge speed={this.state.speed} />。当仪表板调用时this.setState({speed: this.state.speed + 1}),将使用的新值重新显示仪表speed

在发生这种情况之前,componentWillReceiveProps就调用了量规,以便量规有机会将新值与旧值进行比较。


因此听起来像是在React组件初始化并接收道具时被调用一次。一旦创建组件,道具实际上就不会“更改”。那正确吗?
马特·哈金斯

12
相反。该文件说:“当调用组件正在接收新道具不能调用此方法初始渲染。”
瓦雷里

谢谢。这个问题来自对React的最初误解,即重新渲染屏幕(或部分屏幕)时将重用组件。
马特·哈金斯

1
是。组件可以侦听事件,并在每次事件触发时更新其状态。
瓦雷里

8
我来自未来:componentWillReceiveProps现在已经过时了:通过组合所取代getDerivedStateFromPropscomponentDidUpdate
bvdb

53

道具

React组件应该使用道具来存储可以更改的信息,但是只能由其他组件更改。

React组件应该使用状态来存储组件本身可以更改的信息。

Valéry已经提供了一个很好的例子。


4
@ali_adravi是从某处复制的引号吗?如果是这样,参考是什么?还是这些是您的话,您只是将其格式化为引号来强调?
Rob Bednark

@RobBednark我现在不记得确切的来源了,但是可以肯定的是,这句话是对某些书中句子的一些修改。
Ali Adravi

26

当组件的父对象再次使用不同的属性渲染组件时,道具可能会更改。我认为这主要是一种优化,因此不需要实例化任何新组件。


3

欺骗更新道具,如果它们是array:

import React, { Component } from 'react';
import {
  AppRegistry,
  StyleSheet,
  Text,
  View,
  Button
} from 'react-native';

class Counter extends Component {
  constructor(props) {
    super(props);
      this.state = {
        count: this.props.count
      }
    }
  increment(){
    console.log("this.props.count");
    console.log(this.props.count);
    let count = this.state.count
    count.push("new element");
    this.setState({ count: count})
  }
  render() {

    return (
      <View style={styles.container}>
        <Text>{ this.state.count.length }</Text>
        <Button
          onPress={this.increment.bind(this)}
          title={ "Increase" }
        />
      </View>
    );
  }
}

Counter.defaultProps = {
 count: []
}

export default Counter
const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
  welcome: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
  instructions: {
    textAlign: 'center',
    color: '#333333',
    marginBottom: 5,
  },
});

3
我在想用props初始化状态是反模式,应该避免。这是阅读github.com/vasanthk/react-bits/blob/master/anti-patterns/…的好链接。
tryHendri


0

如果您使用recompose,请使用mapProps制作来自传入道具的新道具

编辑例如:

import { compose, mapProps } from 'recompose';

const SomeComponent = ({ url, onComplete }) => (
  {url ? (
    <View />
  ) : null}
)

export default compose(
  mapProps(({ url, storeUrl, history, ...props }) => ({
    ...props,
    onClose: () => {
      history.goBack();
    },
    url: url || storeUrl,
  })),
)(SomeComponent);

请提供示例
vsync
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.