我正在创建一个聊天应用程序,在try 实现链接预览时遇到了一些问题(当您发送链接时,我想从网址加载标题和图像).从下面的代码中您可以看到,我正在映射文本数组中的每个"文本消息",并呈现一个名为ChatMessage的组件.每个ChatMessage组件代表来自组中用户的消息.打开聊天后,消息就会被加载,链接也会被预览.我遇到的问题是,在我从另一个用户发送或接收的每条消息上,所有ChatMessage组件都会重新呈现,因此所有链接都会再次预览(数据再次从网址获取,这导致链接在一瞬间显示网址,然后在从useEffect加载后显示加载的数据).

我怎样才能防止这种情况?如何才能只加载一次链接,而不是每次收到新消息或自己发送新消息时加载链接?下面是代码.

- -

{members.length > 0 && text.map((m, index) => { return <ChatMessage key={index} text={text} m={m} index={index} isMessageSending={isMessageSending} /> })}

-ChatMessage.jsx -

export const ChatMessage = memo(({ text, m, index, isMessageSending }) => {
    // "m" prop is a message object containing message and timestamp when it was sent.
    // "text" prop is all messages in a chat
    const { usersRef } = useContext(PageContext);
    const [userMessageData, setUserMessageData] = useState({});
    const isSentByMe = m.sentBy === auth.currentUser.uid;
    const [linkData, setLinkData] = useState({});

    // this useEffect is supposed to be called when the m.message changes. Why does it get called again when i send a new message? Each message represents this component so it shouldn't be "related" to other messages.
    useEffect(() => {
        if(!m.message) return;

        let foo = async () => {

            if (isValidUrl(m.message)) {
                const data = await fetchDataFromLink(m.message);
                setLinkData(data.result);
            } else {
                setLinkData({});
            }
        }
        foo();
    }, [m.message]);

    return (
        <div> ... </div>
    )

我try 使用备忘录和useCallback加载链接预览,但一旦我点击发送消息按钮,它仍然会继续重新呈现.

推荐答案

A ChatMessage的props 包含textprops ,它是聊天中所有消息的array.当您发送消息时,text数组会更新以将该新消息包含在其列表中,因此该props 的所有依赖项都将被重新呈现.在这种情况下,这将是每一个ChatMessage组件,就像在text.map(..)中,您传递了live text作 for each 组件的props 一样.

memo功能的目的是保留计算.然而,when its component's props are changed,它不会记住,因为从语义上讲,props 可能包括may需要反映在其组件中的"更新数据",因此该组件必须重新渲染(重新计算),然后使用这些新条件记住.如果props 此后保持不变,memo将不会重新渲染.

从提供的代码片段来看,textprops 在每个ChatMessage中似乎都未使用,因此简单的解决方案是将其完全从props 列表中删除,而不是将其传递进go .

如果ChatMessage确实使用了代码中未显示的textprops 中的数据,那么也许可以看看您所需的数据是否可以在某个记忆点或以持续的方式与textprops 分离.核心问题在于,当 for each ChatMessage人提供textprops 时,您是在让他们了解整个聊天的实时数据,而不是成为一个独立的组件.如果ChatMessage不需要广播随后的新聊天,甚至不需要之前的聊天,那么您应该自然而然地将所需的数据与您可能用于每ChatMessagetexts分开.

Reactjs相关问答推荐

使用React Router多姆表单组件附加/?地址栏中基本URL的索引

props 可以在Reaction中锻造吗?

包装组件可以避免子组件重新渲染.?

FireBase Reaction Native-在呈现视图之前等待响应

React,当我调用handleSubmit()函数时,我正在将application/json和multiform/data中的数据发送到后端,但student_image中没有数据:null

如何动态地改变<; Select >;React和Tailwind元素?

在 React 中,为什么不将组件和钩子结合起来呢?

如何管理组件列表的复杂状态? (Nextjs/ReactJS)

如何优化 React 应用程序的性能?

单击按钮时如何添加或删除 3d 对象

从 React 应用程序调用未经身份验证的 graphql 查询时出现错误:没有当前用户

如何使用样式化函数为 TextField 的输入组件设置样式

Suspense/Await - 解析数据加载/保存到状态后无限循环

单元测试 useLoaderData() react-router v6 加载器函数

有没有办法根据 Rechart 中的 activeDot 更改值?

React Native - 身份验证 - 触发值以更改 Auth 和 UnAuth 堆栈导航器

map 未显示在react 传单中

在嵌套的 Stack Navigator 中的 BottomTabBar 中导航会导致比以前更多的渲染

在react 路由dom版本6中的组件内添加路由

在 redux 状态更改时更新react 按钮禁用状态