我可以更新React.js中的组件's props吗?

Can I update a component's props in React.js?

本文关键字:props 组件 React 更新 js 我可以      更新时间:2023-09-26

开始使用React.js后,似乎props是静态的(从父组件传入),而state根据事件变化。然而,我注意到在文档中引用了componentWillReceiveProps,其中具体包括这个例子:

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

这似乎意味着基于nextPropsthis.props的比较,组件的属性可以改变。我错过了什么?道具是怎么变化的,还是我记错了它的名字?

组件不能更新自己的道具,除非它们是数组或对象(让组件更新自己的道具,即使可能也是一种反模式),但可以更新自己的状态和子组件的道具。

例如,Dashboard在其状态中有一个speed字段,并将其传递给显示此速度的Gauge子控件。它的render方法就是return <Gauge speed={this.state.speed} />。当Dashboard调用this.setState({speed: this.state.speed + 1})时,Gauge将使用speed的新值重新渲染。

在此之前,Gauge的componentWillReceiveProps被调用,这样Gauge就有机会将新值与旧值进行比较。

PROPS

React组件应该使用props来存储信息已更改,但只能由其他组件更改

状态

React组件应该使用state来存储信息组件本身可以改变。

val宇航已经提供了一个很好的例子。

当组件的父组件以不同的属性再次呈现该组件时,Props会发生变化。我认为这主要是一种优化,这样就不需要实例化新的组件。

钩子发生了很大的变化,例如componentWillReceiveProps变成了useEffect + useRef(如这另一个SO答案所示),但是Props仍然是只读的,所以只有调用者方法应该更新它。

更新数组道具的技巧:

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,
  },
});

如果使用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);