React:sub.component 不在 main.component 上重新渲染

React: sub.component not re-rendering on main.component

我刚开始学习 React,我遇到了以下问题:SubComponent 在更新状态时没有重新渲染数据。

主组件是视图网页,用于保存所有子组件,逻辑组件管理所有功能,而这个子组件是一个较小的HTML,用于呈现其中一个功能。

主要组件:

import LogicComponent from "./LogicComponent";
import SubComponent from "./SubComponent";
export default function Main() {
  const { getMaintenance } = LogicComponent()
  return (
  <>
    <div onclick={getMaintenance}>CLICK ME</div>
    <SubComponent/>
  </>
  )
}

逻辑组件:

export default function LogicComponent() {
   const [activeMaintenance, setActiveMaintenance] = useState([]);

   async function getMaintenance() {
     getDocs(collection(db, `/maintenance`))
     .then((response) => {
        setActiveMaintenance(
           response.docs.map((doc) => ({
              id: doc.id,
              ...doc.data(),
           }))
        );
     })
     .catch((error) => {
        console.log(error);
     });
   }
   return {
      getMaintenance,
      activeMaintenance,
   }
}

子组件

import LogicComponent from "./LogicComponent";
export default function SubComponent() {
  const { activeMaintenance } = LogicComponent();
  return (
    <>
      {activeMaintenance.map((fileData) => (
        <div key={fileData.id}>{fileData.info}</div>
      ))}
    </>
  )
}

每当 点击我 按钮被触发时,子组件上的数据不会更新,即使正确登录到控制台也是如此。

如果我将 SubComponent 代码放入 MainComponent,它会毫无问题地更新。

・我想知道的是,为什么SubComponent接收到数据后没有重新渲染?

此外,我们非常欢迎任何 React 编程建议。

问题

如评论中所述,您有 2 个 LogicComponent 实例 - 一个在 SubComponent 中,一个在 Main 中。将其想象成具有 class 的 2 个实例 - 每个实例中保存的状态是完全独立的。当您从 Main 调用 getMaintenance 时,您更新了保留在 Main 中的 LogicComponent 实例的状态。 SubComponent 的实例未更新。

解决方案 1

使当前设置正常工作的最简单更改如下:

function SubComponent({ activeMaintenance }) {
  return (
    <>
      {activeMaintenance.map((fileData) => (
        <div key={fileData.id}>{fileData.info}</div>
      ))}
    </>
  );
}

function Main() {
  const { getMaintenance, activeMaintenance } = LogicComponent();
  return (
    <>
      <button onClick={getMaintenance}>CLICK ME</button>
      <SubComponent activeMaintenance={activeMaintenance} />
    </>
  );
}

允许 Main 容纳唯一的 LogicComponent 实例,并将 activeMaintenance 作为 prop 向下传递给 SubComponent。这只是几行更改。这是一个有效的 CodeSandbox(用虚假承诺替换您的数据库调用)。

解决方案 2

您似乎渴望共享状态,在这种情况下您可能需要查看 Context

评论中的另一个注释值得 re-mentioning,您应该考虑将 LogicComponent 重命名为 useMaintenance,因为它本质上是一个 custom hook.

Here 是一个有效的 CodeSandbox,展示了您的应用程序的简单共享全局状态可能是什么样子(使用上下文和挂钩)。