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

时间:2014-07-24 16:50:38

标签: javascript reactjs properties

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

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

这似乎意味着基于nextPropsthis.props的比较,属性可以在组件上发生变化。我错过了什么?道具是如何改变的,还是我错误地将其称为什么?

6 个答案:

答案 0 :(得分:196)

组件无法更新自己的道具,除非它们是数组或对象(即使可能是反模式,组件更新自己的道具),但可以更新其状态及其子项的道具。

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

在此之前,会调用Gauge的componentWillReceiveProps,以便Gauge有机会将新值与旧值进行比较。

答案 1 :(得分:21)

当组件的父级使用不同的属性再次呈现组件时,道具可以更改。我认为这主要是一种优化,因此不需要实例化新的组件。

答案 2 :(得分:18)

道具

  

React组件应使用道具来存储可以   已更改,但只能由其他组件更改。

状态

  

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

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

答案 3 :(得分:2)

如果它们是数组,则欺骗更新道具:

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
      }
    }
  increament(){
    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.increament.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,
  },
});

答案 4 :(得分: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);

答案 5 :(得分:0)

钩子已经发生了很多变化,例如componentWillReceiveProps变成了useEffect + useRefas shown in this other SO answer),但是变成了Props are still Read-Only,因此只有调用者方法才应该对其进行更新。