remix run - 如何重新加载通过 <Outlet/> 加载的组件的所有子组件

jon*_*jon 2 reactjs remix.run

我有一个通过其父级加载的组件。该组件呈现其自己的组件 - ActionsBar 和 Collection。当 URL 更改并且 Outlet 被重新渲染时 - 我的假设是组件内的所有内容都会被重新渲染,但是它似乎只在子组件发生更改时重新渲染它们。

export default function ComponentLoadedInOutlet() {
  const collectionData = useLoaderData();
  return (
    <div>
      <ActionsBar />
      <Collection data={collectionData} />
    </div>
  )
}
Run Code Online (Sandbox Code Playgroud)

在上面的代码片段中,当 URL 更改时重新加载插座时,只有 Collection 组件被重新渲染,因为 collectionData 已更改。

我想知道是否有一种方法可以强制重新加载插座中的所有子组件,这样我就不必费力地重置大量状态。

ris*_*ott 6

您的假设是正确的,当 url 更改时,组件内的所有内容都会重新呈现。然而,重新渲染和重新安装之间存在差异。

当从一个 url 导航到另一个路由到同一组件(即 $dynamic.tsx 段)时,React 只会重新渲染该组件,而不是卸载/挂载该组件。

如果您想保留状态,这可能很有用,但这并不总是可取的。

因此,在 React 中添加一个keyprop 来重置组件层次结构是很常见的。

// /products/$slug.tsx

export const loader = ({ request, params }: LoaderArgs) =>
  json({ slug: params.slug });

export default function ProductDetail() {
  const { slug } = useLoaderData<typeof loader>();
  return (
    // NOTE: `key={slug}`
    <div key={slug}>
      <ActionsBar />
    </div>
  );
}

const ActionsBar = () => {
  useEffect(() => {
    // This will re-mount whenever the `slug` changes
    alert("<ActionBar /> mounted");
  }, []);
  return <div>ActionsBar</div>;
};
Run Code Online (Sandbox Code Playgroud)

这将告诉 React 避免将新树与旧树进行比较,而只是清除旧树,创建一棵全新的树并因此安装循环。