简体   繁体   English

React 组件(react-redux props)不断使用 React.memo() 重新渲染

[英]React component (react-redux props) keeps rerendering with React.memo()

Im building a chat application with react, react-redux and socket.io.我正在使用 react、react-redux 和 socket.io 构建一个聊天应用程序。 Now, to improve the performance of the app i've add React.memo() to my <Message... /> component to prevent the rerenderings.现在,为了提高应用程序的性能,我将React.memo()添加到我的<Message... />组件中以防止重新渲染。 However, according to React Profiler all of my Message components are keeping rerendering, as soon as i fetch further messages.但是,根据 React Profiler,我的所有消息组件都会在我获取更多消息时继续重新渲染。 My code:我的代码:

room.jsx (message container) room.jsx(消息容器)

import { useSelector, useDispatch } from "react-redux";
import {
  fetchMessagesRequest,
  fetchMessagesSuccess,
  fetchMessagesFailure,
  fetchPageMessagesSuccess,
  fetchPageMessagesFailure,
} from "../../redux/actions";

const Room = ({ match, history }) => {

  const dispatch = useDispatch();
  const socket = useSelector((state) => state.socket);
  const room = useSelector((state) => state.room);
  const user = useSelector((state) => state.user);

    <section className='room__content'>
                {room.messages.length ? (
                  <React.Fragment>
                    {room.messages.map((msg, idx) =>
                      idx + 1 === room.messages.length ? (
                        <Message
                          key={msg._id}
                          reference={lastMessageRef}
                          msg={msg}
                          text={msg.message}
                          file={msg.file ? msg.file : ""}
                          date={msg.creationDate}
                          state={msg.state}
                          deleteMessage={() => deleteMessage(msg._id)}
                          likeMessage={() =>
                            broadcastLike(msg._id, user.data.userID)
                          }
                        />
                      ) : (
                        <Message
                          key={msg._id}
                          msg={msg}
                          text={msg.message}
                          file={msg.file ? msg.file : ""}
                          date={msg.creationDate}
                          state={msg.state}
                          deleteMessage={() => deleteMessage(msg._id)}
                          likeMessage={() =>
                            broadcastLike(msg._id, user.data.userID)
                          }
                        />
                      )
                    )}
                    {preload && <Preloader type='inline' />}
                  </React.Fragment>
                ) : (
                  <Placeholder
                    text='No messages'
                    icon='icon icon--bubbles'
                    type='full'
                  />
                )}
              </section>  
    
...

export default withRouter(Room);

message.jsx消息.jsx

import React, { useState, useEffect } from "react";
import "./message.scss";

import { LazyLoadImage } from "react-lazy-load-image-component";

/* REDUX */
import { useSelector, useDispatch } from "react-redux";
import { showGallery, showModal, setMessage } from "../../redux/actions";

const Message = ({
  reference,
  msg,
  text,
  file,
  date,
  state,
  deleteMessage,
  likeMessage,
}) => {
  const [loaded, setLoaded] = useState(false);
  const user = useSelector((state) => state.user);
  const dispatch = useDispatch();

  useEffect(() => {
    let mounted = true;

    axios
      .get(...)
      .then()
      .catch()
      .finally(() => setLoaded(true));

    // CLEANUP
    return () => (mounted = false);
  }, []);

  return (
    <React.Fragment>
      {loaded ? (
        <figure
          ref={reference}
          className={`message${author.tag === user.data.tag ? "--author" : ""}`}
        >
            <div className='message__content'>
              <p className='message__content__text'>{text}</p>
            </div>
        </figure>
      ) : (
        ""
      )}
    </React.Fragment>
  );
};

export default React.memo(Message);

roomReducer.js roomReducer.js

...

case "FETCH_PAGE_MESSAGES_SUCCESS":
  const messages = [...action.payload.messages, ...state.messages];

  return {
    ...state,
    messages: messages
      .filter(
        (v, i, a) =>
          a.findIndex((t) => JSON.stringify(t) === JSON.stringify(v)) === i
      )
      .sort((a, b) => new Date(b.creationDate) - new Date(a.creationDate)),
    total: action.payload.total,
    error: [],
  };

...

Profiler探查器

在此处输入图像描述

This is happening because one or more of the dependencies(props) of Message components are getting updated when you are fetching messages.发生这种情况是因为当您获取消息时,消息组件的一个或多个依赖项(道具)正在更新。 Check if there is any prop depend upon the fetch msg action.检查是否有任何道具取决于 fetch msg 操作。

If there are functions which you are passing to Message component then please wrap them in useCallback hook.如果有要传递给 Message 组件的函数,请将它们包装在useCallback钩子中。

And still if the problem exists you can pass a function to check the prevProps and nextProps in React.memo如果问题仍然存在,您可以通过 function 来检查 React.memo 中的 prevProps 和nextProps

 const isEqual = (prevProps, nextProps) => {}
 React.memo(Message, isEqual)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM