React:为什么即使满足条件,我的条件渲染组件也没有被渲染?

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

在 React 中,有一个父组件,它根据是否有选定的线程有条件地渲染

Output
组件:

<div className="flex-grow overflow-y-auto p-4">
  {myStore.selectedThread ? (
    <Suspense
      fallback={
        <div className="flex justify-center items-center align-middle h-full">
          <Loader active={true} className="w-36 h-36" />
          <p className="text-xs text-gray-500">Loading messages...</p>
        </div>
      }
    >
      <Output loading={loading} />
    </Suspense>
  ) : (
    <div className="flex flex-col items-center justify-center h-full">
      <h1 className="text-6xl font-bold text-violet-900 mb-4">
        Hi, {store.profile.fname} {store.profile.lname}!
      </h1>
      <p className="text-gray-500 text-xl mb-8">
        Hit record and let the magic begin.
      </p>
      <RecordingComponent myStore={myStore} />
    </div>
  )}
</div>

并且,在父组件内的

RecordingComponent
中,我在
handlePostTranscription()
函数之后使用 MobX 存储函数选择一个线程:

const audioTranscriberStatus =
  myStore.inputActiveRecord?.audioTranscriber?.status;
console.log(audioTranscriberStatus);
useEffect(() => {
  const handlePostTranscription = async () => {
    const { inputActiveRecord, selectedThread } = myStore;
    if (!inputActiveRecord || selectedThread) {
      return;
    }

    try {
      const newThread = await createThread();
      const newThreadId = newThread.thread_id;
      setForceRender((prev) => !prev);

      await updateHistory(inputActiveRecord._id, { threadId: newThreadId });
      const transcriptionText = inputActiveRecord.outputs.join(" ");
      await addMessage(newThreadId, "user", transcriptionText);
      await runAssistant(
        transcriptionText,
        newThreadId,
        "asst_L24bszgfqSOxw3yT0dTOaIzZ",
        "",
      );

      myStore.selectThread(newThreadId);
      console.log(myStore.selectedThread);
    } catch (error) {
      console.error("Error in post-transcription handling:", error);
    }
  };

  if (audioTranscriberStatus === "done") {
    handlePostTranscription();
  }
}, [audioTranscriberStatus]);

在调试日志中,我可以看到它正确设置了线程,这意味着

myStore.selectedThread
为 true,应该渲染
Output
组件。

但是,我的问题是在父组件中,

Output
没有渲染——我仍然看到欢迎屏幕。当我使用
HistoryPanel
组件或
TextInputComponent
组件设置线程时,情况并非如此。它们似乎都使
Output
组件渲染成功。

来自

TextInputComponent

const handleTextSubmit = async () => {
  try {
    setLoading(true);

    // Save the text using the API that goes through the middleware
    const response = await saveText(message);

    if (response.data.history && response.data.history._id) {
      const fetchedHistory = response.data.history;
      let currentThreadId = fetchedHistory.threadId;

      if (!currentThreadId) {
        // Create a new thread if none exists
        const newThread = await createThread();
        currentThreadId = newThread.thread_id;

        // Update history with the new thread ID
        await updateHistory(fetchedHistory._id, {
          threadId: currentThreadId,
        });
      }

      // Add the message to the thread
      await addMessage(currentThreadId, "user", message);

      // Run the assistant on the message
      await runAssistant(
        message,
        currentThreadId,
        "asst_L24bszgfqSOxw3yT0dTOaIzZ",
        "",
      );

      myStore.selectThread(currentThreadId);
    }
  } catch (error) {
    console.error(error);
  } finally {
    setMessage("");
    setLoading(false);
  }
};

来自

HistoryPanel

    const handleHistoryClick = async (threadId) => {
      try {
        setSelectedThreadId(threadId);
        myStore.selectThread(threadId);
      } catch (error) {
        console.error("Error selecting thread:", error);
      }
    };

最后,我的商店:

  selectThread = async (threadId) => {
    if (this.selectedThread !== threadId) {
      this.selectedThread = threadId;
      await this.fetchThreadMessages(threadId);
    }
  };

请问有人知道是什么原因造成的吗?

我还尝试将查询参数添加到具有

threadId
的 url 中,并在 url 具有此参数时渲染
Output
组件,但是,在
handlePostTranscription()
函数中,当我使用
window.location.href
甚至
useHistory
,它甚至没有改变网址。所以异步函数肯定有什么东西搞砸了。

javascript reactjs react-hooks conditional-statements mobx-react
1个回答
0
投票

您已更改

myStore
上的对象属性,但 React 只监视外部对象,而不是其属性

当你改变它所监视的内容时,React 会更新 DOM;然后它可以重新运行您的函数或重新渲染您的组件并对 DOM 进行更改。

我们看不到您的

myStore
,但即使它是
useState
变量,它们也只能使用 Object.is 通过
浅相等
进行比较。你已经改变了它的状态,但 React 不知道要注意这一点。你的 TextInputComponent 和 HistoryPanel 意外地通过它们的
setMessage
setLoading
setSelectedThreadId
触发了这个,这可能会以 React 可以看到的方式改变状态变量;
myStore
的更新是在您的两个工作组件中意外发生的。

尽管有一些令人沮丧的方法来强制重新渲染(请参阅可以在不调用 setState 的情况下强制 React 组件重新渲染吗?),但最好的选择可能是调用

setSelectedThreadId
或创建一个新的状态变量(例如
setTranscriptionUpdateTimestamp
)将数据更改反映到您尝试更新的组件。

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