javascript - React 组件(react-redux props)不断使用 React.memo() 重新渲染
问题描述
我正在使用 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: [],
};
...
探查器
解决方案
发生这种情况是因为当您获取消息时,消息组件的一个或多个依赖项(道具)正在更新。检查是否有任何道具取决于 fetch msg 操作。
如果有要传递给 Message 组件的函数,请将它们包装在useCallback钩子中。
如果问题仍然存在,您可以传递一个函数来检查 React.memo 中的 prevProps 和nextProps
const isEqual = (prevProps, nextProps) => {}
React.memo(Message, isEqual)
推荐阅读
- python - Flask Python 身份验证错误:identity = getattr(identity, 'id') 或 identity['id']
- angular - 如何创建响应式导航栏,如 clickup.com
- php - 在多维数组中查找具有空值的元素
- c# - 检索和反序列化大型 Redis 缓存项列表
- powerbi - 如何计算power bi中的平均库存?
- java - android.support.design.widget.TabLayout - 无法解析符号“设计”
- python-3.x - 如何在评估python列表中的每个项目时减少执行时间
- android - Android BitmapFactory.decodeByteArray 获取照片宽度/高度比iOS UIImage(data:)
- php - 如何使用 PHP 和 VUEJS 将 2 个文件从 2 个单个输入文件上传到数据库
- python - 如何从 xlwings 调用 Excel 函数