我正在使用 react、react-redux 和 socket.io 构建一个聊天应用程序。现在,为了提高应用程序的性能,我添加React.memo()
到我的<Message ... />
组件中以防止重新渲染。但是,根据 React Profiler,我的所有消息组件都会在我获取更多消息时继续重新渲染。我的代码:
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);
消息.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: [],
};
...
探查器