我可以在 React.js 中更新组件的 props 吗?
Posted
技术标签:
【中文标题】我可以在 React.js 中更新组件的 props 吗?【英文标题】:Can I update a component's props in React.js? 【发布时间】:2014-09-16 08:34:45 【问题描述】:开始使用 React.js 后,props
似乎是静态的(从父组件传入),而 state
根据事件发生变化。但是,我注意到文档中提到了componentWillReceiveProps
,其中特别包括了这个例子:
componentWillReceiveProps: function(nextProps)
this.setState(
likesIncreasing: nextProps.likeCount > this.props.likeCount
);
这似乎意味着可以根据nextProps
与this.props
的比较来更改组件的属性。我错过了什么? props 是如何变化的,还是我弄错了它的调用位置?
【问题讨论】:
【参考方案1】:一个组件不能更新它自己的 props,除非它们是数组或对象(让一个组件更新它自己的 props,即使可能是一种反模式),但是可以更新它的 state 和它的孩子的 props。
例如,Dashboard 在其状态中有一个speed
字段,并将其传递给显示此速度的 Gauge 子项。它的render
方法就是return <Gauge speed=this.state.speed />
。当仪表板调用this.setState(speed: this.state.speed + 1)
时,仪表会使用speed
的新值重新渲染。
就在这发生之前,调用 Gauge 的 componentWillReceiveProps
,以便 Gauge 有机会将新值与旧值进行比较。
【讨论】:
所以听起来像是在 React 组件初始化并接收 props 时调用了一次。一旦创建了组件,这些道具实际上并没有“改变”。对吗? 相反。 documentation 表示:“在组件接收新道具时调用。初始渲染不调用此方法。” 谢谢。这个问题源于最初对 React 的误解,即在重新渲染屏幕(或屏幕的一部分)时会重用组件。 是的。组件可以监听事件,并在每次事件触发时更新其状态。 我来自未来:componentWillReceiveProps
现在已经过时了:取而代之的是getDerivedStateFromProps
和componentDidUpdate
的组合。【参考方案2】:
道具
一个 React 组件应该使用 props 来存储可以被 已更改,但只能由不同的组件更改。
状态
React 组件应该使用状态来存储 组件本身可以改变。
Valéry 已经提供了一个很好的例子。
【讨论】:
@ali_adravi 那些引号是从某个地方复制过来的吗?如果有,参考是什么?或者这些是你的话,而你只是将它们格式化为强调的引号? 我发现自己在说,“但我两个都需要?!”我最终从子组件中重构了一些逻辑,并将其移动到可以作为属性传递给子组件的父组件中。感觉有点不对劲,但现在可以正常运行了;这就像对 roids 的依赖注入。如果你有逻辑你总是希望子组件表达并且不想在父组件中重新实现它,那么它可能会很烦人。当然,我还有更多关于这种情况的知识。【参考方案3】:当组件的父级使用不同的属性再次渲染组件时,道具可能会发生变化。我认为这主要是一种优化,因此不需要实例化新组件。
【讨论】:
【参考方案4】:钩子发生了很大变化,例如componentWillReceiveProps
变成了useEffect
+useRef
(as shown in this other SO answer),但是Props are still Read-Only,所以只有调用者方法应该更新它。
【讨论】:
【参考方案5】:如果道具是数组,则更新道具的技巧:
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,
,
);
【讨论】:
我认为使用道具初始化状态是反模式,应该避免。这是阅读github.com/vasanthk/react-bits/blob/master/anti-patterns/…的好链接。【参考方案6】:如果您使用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);
【讨论】:
以上是关于我可以在 React.js 中更新组件的 props 吗?的主要内容,如果未能解决你的问题,请参考以下文章
在 react js 功能组件中调度操作后如何立即在 redux store 中使用更新的值