反应组件无限更新

时间:2018-08-28 20:37:47

标签: reactjs redux react-redux

我有一个React组件,每当我将其连接到redux并引用商店中的属性时,该组件上的更新都会无限。如果我只是从存储中引用/连接一个属性,则不会发生无限更新。只有当我连接两个或多个时,才会发生这种情况,而我真的无法确定为什么会发生这种情况。

当我添加shouldComponentUpdate时,它实际上不会停止无限更新,只会减慢很多速度。我真的不知道发生了什么。

更新: 有趣的是,如果仅取出componentDidUpdate函数,它将不会进行无限循环并导致浏览器崩溃。

import React, { Component } from 'react';

import { connect } from 'react-redux';

class UnreadMessages extends Component {
    constructor(props) {
        super(props);

        this.state = {
            messageReceived: false,
            unreadMessages: 0
        }

        this.unreadMessages = 0;
    }

    componentDidUpdate(prevProps, prevState) {
        if (prevProps.lastViewedMessageTime === this.props.lastViewedMessageTime) {
            this.setState({ messageReceived: true }, 
                () => {
                    setTimeout(
                        () => {
                            this.setState({ messageReceived: false });
                        }, 
                        300
                    );
                }
            );
        }

        const conOne = prevProps.messages.length !== this.props.messages.length;
        const conTwo = this.props.visible === false && window.innerWidth < 768;
        if (conTwo) {
            let index = this.props.messages.length - 1;
            const conOne = this.props.messages[index].type === 'chat.msg';
            const conTwo = this.props.messages[index].member_type === 'agent';
            if (conOne && conTwo) {
                this.setState({ 
                    unreadMessages: this.state.unreadMessages + 1 
                });
            }
        }

        if (this.props.visible === true) {
            this.setState({ unreadMessages: 0 });
        }
    }

    render () {
        let displayBadge = this.state.unreadMessages > 0 ? true : false;
        console.log('DISPLAY BAD', displayBadge)
        let pulse = this.state.messageReceived === true ? 'pulse' : '';
        console.log('PULSE', pulse)

        if (!displayBadge) {
            return null;
        }

        return (
            <span className={`msgBadge ${pulse}`}>{this.state.unreadMessages}</span>
        )
    }
}

function mapStateToProps(state) {
  return {
    lastViewedMessageTime: state.lastViewedMessageTime,
    messages: state.chats.toArray(),
    visible: state.visible
  };
}
export default connect(mapStateToProps, null)(UnreadMessages);

1 个答案:

答案 0 :(得分:1)

正如@Hamms在评论中指出的那样,在this.setState中使用componentDidUpdate很可能会引起问题。

采用componentDidUpdate的前几行。

componentDidUpdate(prevProps, prevState) {
    if (prevProps.lastViewedMessageTime === this.props.lastViewedMessageTime) {
        this.setState({ messageReceived: true }, 
     ...

如果状态或除lastViewedMessageTime之外的任何其他道具发生更改并导致更新,则lastViewedMessageTime道具在当前道具中将与prevProps中的相同。

这将导致状态更改-因此进行更新-lastViewedMessageTime也是如此。

您已经陷入了无休止的更新周期。

您应该查看static getDerivedStateFromPropsmemoization。这些应该有助于避免这些问题。