道具更改时重新呈现 React 组件

我试图将表示组件从容器组件中分离出来。我有一个 SitesTable和一个 SitesTableContainer。容器负责触发 redux 操作,以根据当前用户获取适当的站点。

问题是当前用户是在容器组件最初呈现之后异步获取的。这意味着容器组件不知道它需要重新执行其 componentDidMount函数中的代码,这将更新要发送给 SitesTable的数据。当容器组件的一个道具(用户)发生变化时,我认为我需要重新呈现容器组件。我该怎么做才正确呢?

class SitesTableContainer extends React.Component {
static get propTypes() {
return {
sites: React.PropTypes.object,
user: React.PropTypes.object,
isManager: React.PropTypes.boolean
}
}


componentDidMount() {
if (this.props.isManager) {
this.props.dispatch(actions.fetchAllSites())
} else {
const currentUserId = this.props.user.get('id')
this.props.dispatch(actions.fetchUsersSites(currentUserId))
}
}


render() {
return <SitesTable sites={this.props.sites}/>
}
}


function mapStateToProps(state) {
const user = userUtils.getCurrentUser(state)


return {
sites: state.get('sites'),
user,
isManager: userUtils.isManager(user)
}
}


export default connect(mapStateToProps)(SitesTableContainer);
288609 次浏览
componentWillReceiveProps(nextProps) { // your code here}

我觉得这才是你需要的。每当你的组件通过道具接收到一些东西时,就触发 componentWillReceiveProps触发器。从那里你可以检查,然后做你想做的任何事情。

我建议你看看我的这个 回答,看看它是否与你正在做的事情有关。如果我理解你真正的问题,那就是你没有正确使用你的异步操作和更新 reducx“ store”,它会自动更新你的组件和它的新道具。

代码的这一部分:

componentDidMount() {
if (this.props.isManager) {
this.props.dispatch(actions.fetchAllSites())
} else {
const currentUserId = this.props.user.get('id')
this.props.dispatch(actions.fetchUsersSites(currentUserId))
}
}

不应该在组件中触发,应该在执行第一个请求后处理。

看看 再来一次中的这个例子:

function makeASandwichWithSecretSauce(forPerson) {


// Invert control!
// Return a function that accepts `dispatch` so we can dispatch later.
// Thunk middleware knows how to turn thunk async actions into actions.


return function (dispatch) {
return fetchSecretSauce().then(
sauce => dispatch(makeASandwich(forPerson, sauce)),
error => dispatch(apologize('The Sandwich Shop', forPerson, error))
);
};
}

您不一定非得使用 redux-thunk,但是它可以帮助您对这样的场景进行推理,并编写与之匹配的代码。

您必须在 componentDidUpdate方法中添加一个条件。

这个例子是使用 fast-deep-equal来比较对象。

import equal from 'fast-deep-equal'


...


constructor(){
this.updateUser = this.updateUser.bind(this);
}


componentDidMount() {
this.updateUser();
}


componentDidUpdate(prevProps) {
if(!equal(this.props.user, prevProps.user)) // Check if it's a new user, you can also use some unique property, like the ID  (this.props.user.id !== prevProps.user.id)
{
this.updateUser();
}
}


updateUser() {
if (this.props.isManager) {
this.props.dispatch(actions.fetchAllSites())
} else {
const currentUserId = this.props.user.get('id')
this.props.dispatch(actions.fetchUsersSites(currentUserId))
}
}

使用钩子(React 16.8.0 +)

import React, { useEffect } from 'react';


const SitesTableContainer = ({
user,
isManager,
dispatch,
sites,
}) => {
useEffect(() => {
if(isManager) {
dispatch(actions.fetchAllSites())
} else {
const currentUserId = user.get('id')
dispatch(actions.fetchUsersSites(currentUserId))
}
}, [user]);


return (
return <SitesTable sites={sites}/>
)


}

如果要比较的道具是对象或数组,则应使用 useDeepCompareEffect而不是 useEffect

由于缺陷和不一致性,componentWillReceiveProps()将在未来被弃用。在道具更换时重新渲染组件的另一种解决方案是使用 componentDidUpdate()shouldComponentUpdate()

如果 shouldComponentUpdate()返回 true (如果没有定义 shouldComponentUpdate(),它默认返回 true) ,则在组件更新时调用 componentDidUpdate()

shouldComponentUpdate(nextProps){
return nextProps.changedProp !== this.state.changedProp;
}


componentDidUpdate(props){
// Desired operations: ex setting state
}

同样的行为也可以通过包含 If判断语句内部的 componentDidUpdate()方法来实现。

componentDidUpdate(prevProps){
if(prevProps.changedProp !== this.props.changedProp){
this.setState({
changedProp: this.props.changedProp
});
}
}

如果试图在没有条件或没有定义 shouldComponentUpdate()的情况下设置状态,组件将无限重新呈现

您可以使用 KEY独特的关键字(数据的组合) ,随着道具的变化,该组件将被更新的道具重新呈现。

一个友好的使用方法如下,一旦道具更新,它将自动重新呈现组件:

render {


let textWhenComponentUpdate = this.props.text


return (
<View>
<Text>{textWhenComponentUpdate}</Text>
</View>
)


}

您可以在希望重新呈现的组件中使用 getDerivedStateFromProps()生命周期方法,根据传递给组件的 props的传入更改来设置组件的状态。更新状态将导致重新呈现。工作原理是这样的:

static getDerivedStateFromProps(nextProps, prevState) {
return { myStateProperty: nextProps.myProp};
}

这将把组件状态中 myStateProperty的值设置为 myProp,然后组件将重新呈现。

确保您了解使用这种方法的潜在影响。特别是,您需要避免无意中覆盖组件的状态,因为 props在父组件中进行了意外更新。如果需要,可以通过比较现有状态(由 prevState表示)和任何传入的 props值来执行检查逻辑。

只有在来自 props的值是状态值的真值来源的情况下,才使用更新后的道具来更新状态。如果是这样的话,也许还有一个更简单的方法来实现你的需求。看-你可能不需要派生状态反应博客