如何从 React 中的同级组件更新状态

问题描述 投票:0回答:1

我有一个带有侧面板和主面板的网页。主面板是聊天屏幕。我那里有以下代码。

const MainPanel = (({ chatList }) => {

  const [userChat, setUserChat] = useState('');
  const [chatArray, setChatArray] = useState([]);

  function handleSubmit(e) {
    e.preventDefault();
    // Some UI login here
    postChatEntry(newMessage);
  }

  async function postChatEntry(message) {
    const request = new Request("/chat", {
      method: "POST",
      body: JSON.stringify({ message: message.chatEntry })
    });

    const response = await fetch(request);
    const jsonResponse = await response.json();
    if (jsonResponse) {
      chatArray.push(jsonResponse.reply);
      const deepCopy = [...chatArray]
      setChatArray(deepCopy);
    }
  }

  return (
    <section>
      <div>
        {chatArray.map((message) => {
           <ChatBubble chat={message} key={message.id} />
        })}
      </div>
      <form id="chatForm" onSubmit={handleSubmit}>
        <input
          placeholder='Type your message here...'
          value={userChat}
          onChange={(e) => setUserChat(e.target.value)}></input>
        <button>Post</button>
      </form>
    </section>
  )
})

现在,在我的侧面板中,我有用于清除聊天和加载历史记录的按钮。当我点击这些按钮时,我正在MainPanel 中的聊天部分进行更新。 在我的侧面板中,我有以下内容。

const SidePanel = (({ setChatList }) => {

  function loadHistory(e) {
    e.preventDefault();
    fetch('/history').then((res) => res.json()).then((data) => {
      const list = parseResponse(data)
      setChatList(list);
    });
  }

  return (
    <div>
      <ul>
        <li>
          <a onClick={loadHistory}>Clear Chat</span></a>
        </li>
      </ul>
    </div>
  )
})

在我的应用程序(SidePanel 和 MainPanel 的父级)中,我有以下内容:

function App() {

  const [chatList, setChatList] = useState([]);

  return (
     <div className="col-auto col-md-3 col-xl-2 px-sm-2 px-0 bg-dark">
       <div className="d-flex flex-column align-items-center">
          <SidePanel setChatList={setChatList} />
       </div>
       <div className="col py-3 h-100">
          <MainPanel chatList={chatList} />
       </div>
     </div>
  );
}

从上面的代码中,我在主面板中有一个状态(chatArray),我可以在每次进行 API 调用时使用它来更新 dom。但是,当我从侧面板获取刷新值时,我无法在主面板中更新它。 我对 React 很陌生(一周前开始学习)。任何建议都会有所帮助。

我尝试使用在 SidePanel 中更新并通过应用程序传递到 MainPanel 的相同状态(chatList),而不是在 MainPanel 中拥有单独的状态(chatArray)。这不起作用 - 通过这种方法,侧面板中的值现在在主面板中刷新。但 MainPanel 内的 API 响应不会反映出来。

reactjs
1个回答
0
投票

请强制组件 MainPanel 在组件 SidePanel 中每次运行 loadHistory 事件时呈现。

目前您已将 chatList 传递到 MainPanel,但它尚未在那里呈现。它必须在组件 MainPanel 中呈现。不仅如此,每当您单击“清除聊天”时,MainPanel 组件都必须重新呈现聊天历史记录。这两个功能可以通过以下方式实现。

a) 使用 key 强制在每次单击“清除聊天”时呈现 MainPanel。要了解更多信息,请参阅文档 使用密钥重置状态

  <div className="col py-3 h-100">
    <MainPanel key={Math.random()} chatList={chatList} />
  </div>

b) 请在MainPanel中为chatList添加单独的渲染逻辑,如下所示。

{chatArray.length == 0 &&
  chatList.map((message, i) => (
    <Fragment key={i}>
      <label>{message}</label>
      <br />
    </Fragment>
  ))}

修改后的代码的完整列表和测试结果

请注意 API 调用和问题中未包含源的组件已被适当替换 要了解工作版本的完整性,请在此处进行演示。

import { Fragment, useState } from 'react';

export default function App() {
  const [chatList, setChatList] = useState([]);

  return (
    <div className="col-auto col-md-3 col-xl-2 px-sm-2 px-0 bg-dark">
      <div className="d-flex flex-column align-items-center">
        <SidePanel setChatList={setChatList} />
      </div>
      <div className="col py-3 h-100">
        <MainPanel key={Math.random()} chatList={chatList} />
      </div>
    </div>
  );
}

const MainPanel = ({ chatList }) => {
  const [userChat, setUserChat] = useState('');
  const [chatArray, setChatArray] = useState([]);

  function handleSubmit(e) {
    e.preventDefault();
    // Some UI login here
    //    postChatEntry(newMessage); // commented for the MRE
    postChatEntry(userChat); // added for the MRE
  }

  async function postChatEntry(message) {
    // const request = new Request('/chat', {
    //   method: 'POST',
    //   body: JSON.stringify({ message: message.chatEntry }),
    // });

    // const response = await fetch(request);
    // const jsonResponse = await response.json();
    // if (jsonResponse) {
    //chatArray.push(jsonResponse.reply); //
    const deepCopy = [...chatArray, message];
    setChatArray(deepCopy);
    setUserChat('');
    // }
  }

  return (
    <section>
      <div>
        {chatArray.length == 0 &&
          chatList.map((message, i) => (
            <Fragment key={i}>
              <label>{message}</label>
              <br />
            </Fragment>
          ))}
        {chatArray.map((message, i) => (
          <Fragment key={i}>
            <label>{message}</label>
            <br />
          </Fragment>
        ))}
      </div>
      <form id="chatForm" onSubmit={handleSubmit}>
        <input
          placeholder="Type your message here..."
          value={userChat}
          onChange={(e) => setUserChat(e.target.value)}
        ></input>
        <button>Post</button>
      </form>
    </section>
  );
};

const SidePanel = ({ setChatList }) => {
  function loadHistory(e) {
    e.preventDefault();
    // fetch('/history')
    //   .then((res) => res.json())
    //   .then((data) => {
    //     const list = parseResponse(data);
    //     setChatList(list);
    //   });
    setChatList(['chat-1', 'chat-2', 'chat-3']);
  }

  return (
    <div>
      <ul>
        <li>
          <a onClick={loadHistory}>Clear Chat</a>
        </li>
      </ul>
    </div>
  );
};

测试结果

加载应用程序时

On loading the App

在新聊天中

Ona new Chat

从聊天记录加载后

After loading from Chat history

© www.soinside.com 2019 - 2024. All rights reserved.