在 Redux Reducer 或组件的 ShouldComponentUpdate 中进行深度比较?

Posted

技术标签:

【中文标题】在 Redux Reducer 或组件的 ShouldComponentUpdate 中进行深度比较?【英文标题】:Deep Compare in Redux Reducer or in Component's ShouldComponentUpdate? 【发布时间】:2020-09-06 06:47:08 【问题描述】:

在我的 React Redux 应用程序中,setInterval() 不断调用操作创建者 this.props.getLatestNews() 来查询 REST API 端点。在获取 API 响应(对象数组)后,它将以响应数组作为有效负载分派一个动作。

反应组件

class Newsfeed extends Component 
    constructor(props) 
        super(props);
        this.state =  ... 
    

    componentWillMount() 
        this.updateTimer = setInterval(() =>  this.props.getLatestNews() , 1000);
    

    componentWillUnmount() 
        clearInterval( this.updateTimer );
    

    shouldComponentUpdate(nextProps, nextState) 
        // Should we do a deep compare of nextProps & this.props, 
        // shallow compare of nextState & thisState?
    

    render() 
        return ( ... )
    


const mapStateToProps = (state) => (
    newsfeed: state.newsfeed
);

const mapDispatchToProps = (dispatch) => 
    return 
        getLatestNews: () => dispatch(getLatestNews())
    
;

export default connect(mapStateToProps, mapDispatchToProps)(Newsfeed);

在reducer中,目前总是更新部分状态,不管有没有变化

减速器

export default function newsfeedReducer(state=initialState, action) 
    switch (action.type) 
        case NEWSFEED_RECEIVED:
            // Or should we do the deep compare of `action.payload` with `state.items` here?
            return  ...state, items: action.payload 

        default:
            return state
    

Root Reducer

...

const rootReducer = combineReducers(
    newsfeed: newsfeedReducer
);

...

大多数时候,当收到 API 结果时,Redux 存储中没有不存在的新项目。如果reducer仍然用API结果替换了store的这一部分,由于新对象引用props,连接的组件将重新渲染,除非我们在shouldComponentUpdate()内部进行深度比较。

为了避免对 React 组件进行不必要的重新渲染,我正在考虑在 shouldComponentMount() 函数中对当前和下一个道具进行深度比较,或者对 action.payload 与 @ 进行深度比较987654330@ 应该替换它。

进行深度比较的推荐位置在哪里?或者这根本没有必要?

谢谢!

【问题讨论】:

什么是shouldComponentMount?你的意思是shouldComponentUpdate?那将是您进行比较的地方。 @jmargolisvt 抱歉打错了,应该是shouldComponentUpdate 您的意思是mapStateToProps = (state) => ( newsfeed: state.items )?否则 state.items 更改不会影响此组件。 是的,我确实建议您在 newsfeedReducer() 中进行深入比较。 @hackape 对不起,我忘了包括 NEWSFEED_RECEIVED 的减速器被传递到根减速器的事实。更新的问题。 【参考方案1】:

一般来说,在使用 redux 时,我们可以做出一些选择来避免重新渲染。

    在 Reducer 中: 比较当前状态和 api/action 有效负载结果,即您的可能/下一个状态。只需在减速器中返回以前的状态,就不会导致重新渲染 在组件中:如果您的比较取决于您的组件属性,则使用shouldComponentUpdate,它为您提供nextPropsnextState 作为参数。 In Actions:如果您想进行条件调度(即,如果对 api-results 不满意,则调度其他内容)然后在您的操作中进行比较。您可以使用getState 访问当前状态。

注意 - 即使你使用 Pure 组件,组件仍然会重新渲染,因为即使对象值相同,状态的对象引用也会改变。

第 1 点的演示 - shouldComponentUpdate

第 2 点的演示 - state-reducer-etc

【讨论】:

以上是关于在 Redux Reducer 或组件的 ShouldComponentUpdate 中进行深度比较?的主要内容,如果未能解决你的问题,请参考以下文章

React + Redux:reducer 不会重新加载组件

React 组件没有得到 reducer 设置的 redux 初始状态

如何渲染存储在 redux reducer 中的 reactjs 组件?

在组件内调用多个操作时 Redux Reducer 的行为

动态生成 Redux Reducer

在 redux 中使用样板动作和 reducer