Компонент React (react-redux props) продолжает повторную обработку с помощью React.memo()

#javascript #reactjs #redux #react-redux #react-memo

#javascript #reactjs #redux #react-redux #react-memo

Вопрос:

Я создаю приложение для чата с помощью react, react-redux и socket.io . Теперь, чтобы повысить производительность приложения, я добавил React.memo() его в свой <Message ... /> компонент, чтобы предотвратить повторную визуализацию. Однако, согласно профилировщику React, все мои компоненты сообщений продолжают повторную обработку, как только я получаю дополнительные сообщения. Мой код:

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 amp;amp; <Preloader type='inline' />}
                  </React.Fragment>
                ) : (
                  <Placeholder
                    text='No messages'
                    icon='icon icon--bubbles'
                    type='full'
                  />
                )}
              </section>  
    
...

export default withRouter(Room);
 

message.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

 ...

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: [],
  };

...
 

Профилировщик

введите описание изображения здесь

Ответ №1:

Это происходит потому, что одна или несколько зависимостей (реквизитов) компонентов сообщений обновляются при получении сообщений. Проверьте, есть ли какая-либо опора, зависящая от действия fetch msg.

Если есть функции, которые вы передаете компоненту сообщения, пожалуйста, оберните их в useCallback hook.

И все же, если проблема существует, вы можете передать функцию для проверки предварительных и последующих запросов в React.memo

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