React 状态不会更新,并且列表不会重新呈现

Posted

技术标签:

【中文标题】React 状态不会更新,并且列表不会重新呈现【英文标题】:React state doesnt upate and list doesnt get rerendered 【发布时间】:2021-10-10 19:07:27 【问题描述】:

简而言之:

我有一个包含对象列表的状态变量

当我单击一个按钮时,会调用一个方法,该方法会使用 setState 方法将一个对象添加到列表中。

状态不更新。 此外,列表应该使用 .map 函数呈现

短代码(仅重要部分)

const [chat, setChat] = useState([]);

...

function addMessage(msg: Message) 
    let newChat = chat;
    // @ts-ignore
    newChat.push(msg);
    setChat(newChat);
  

...

chat.map((e: Message) => (
          <Message
            key=e.msg
            content=e.msg
            author=e.author
            self=e.author === self
          />
        ))

...

<Messageinput
        sendMessage=(m) => 
          addMessage( msg: m, author: "You" );
        

完整代码(整个组件)

interface Message 
  msg: string;
  author: string;


export default function Chat(
  messages,
  self,
: 
  messages: Array<Message>;
  self: string;
) 
  const [chat, setChat] = useState([]);

  useEffect(() => 
    // @ts-ignore
    setChat(messages);
  , []);

  function addMessage(msg: Message) 
    let newChat = chat;
    // @ts-ignore
    newChat.push(msg);
    setChat(newChat);
  

  useEffect(() => 
    console.log("chat state changed: ", chat);
  , [chat]);

  return (
    <div
      className="flex flex-col bg-white bg-opacity-10 rounded-3xl p-4 max-w-sm"
      style= maxHeight: "720px", height: "100%" 
    >
      <div className="overflow-y-auto h-full">
        chat.map((e: Message) => (
          <Message
            key=e.msg
            content=e.msg
            author=e.author
            self=e.author === self
          />
        ))
      </div>
      <Messageinput
        sendMessage=(m) => 
          addMessage( msg: m, author: "You" );
        
      />
    </div>
  );

【问题讨论】:

【参考方案1】:

您可能希望像这样更新状态:

function addMessage(msg: Message) 
    setChat(prev => [ ...prev , msg]);
  

【讨论】:

【参考方案2】:

您的问题出在您的 addMessage 函数中:

let newChat = chat;
newChat.push(msg);
setChat(newChat);

您正在改变现有数组,然后将状态变量设置为新数组。我建议在useState 周围阅读the documentation,因为你刚才所做的完全错误。

要么先复制newChat,要么使用mutator函数方法:

setChat([...chat, msg]);
// or
setChat(arr => [...arr, msg]);

在 React 中,几乎不应该直接改变状态,而是用不同的值复制状态。因为你用它已经设置的值调用setChat,所以 React 基本上会“哦,状态变量已经是那个值,不需要重新渲染”,这就是它不更新的原因。

【讨论】:

以上是关于React 状态不会更新,并且列表不会重新呈现的主要内容,如果未能解决你的问题,请参考以下文章

即使 DB 已正确更新,React UI 也不会在单击时重新呈现。第二次点击后,UI 重新渲染

如何使用 Apollo Query 构造 React 代码,以便随机查询的对象数组不会随着状态变化而重新呈现?

在 Safari 中状态更改后,React 组件不会重新呈现

OnSubmit 函数不会更新 React 中的反应钩子状态变量

React.useState 不会从 props 重新加载状态

图标类名不会在状态更改时更新