我可以更新一个组件's道具在React.js?

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

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

这似乎意味着,基于nextPropsthis.props的比较,组件的属性可以改变。我错过了什么?道具是如何变化的,或者我弄错了这个在哪里被调用?

428157 次浏览

当一个组件的父组件以不同的属性再次呈现该组件时,道具可以改变。我认为这主要是一种优化,这样就不需要实例化新的组件了。

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

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

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

如果道具是数组,更新道具的技巧:

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

道具

React组件应该使用props来存储可以存储的信息 已更改,但只能由不同的组件更改

状态

React组件应该使用state来存储信息

.组件本身可以改变

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

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

钩子已经改变了很多,例如componentWillReceiveProps变成了useEffect+useRef (正如这个SO答案所示),但是道具仍然是只读的,所以只有调用者方法应该更新它。