You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何避免SolidJS页面切换时Home组件重渲染与重复API调用?

解决SolidJS路由返回时Home组件重复请求API的问题

核心原因

SolidJS默认路由行为是:每次导航到新路由时,原路由组件会被卸载;返回目标路由时,组件会重新挂载。这就导致Home组件的onMount在返回时再次执行,触发不必要的API调用。

解决方案

方案1:状态提升到路由外层(最简单可靠)

把items的状态移到路由的父组件(比如根组件App),这样Home组件卸载时状态不会丢失,返回时直接复用已有数据,无需重新请求。

修改根组件:

import { createSignal, onMount } from 'solid-js';
import { Routes, Route } from '@solidjs/router';
import Home from './Home';
import Detail from './Detail';

export default function App() {
  const [items, setItems] = createSignal<Item[]>([]);

  // 仅在App挂载时请求一次数据
  onMount(async () => {
    setItems(await fetchItemsThroughExpensiveAPI());
  });

  return (
    <Routes>
      <Route path="/" element={<Home items={items()} />} />
      <Route path="/item/:id" element={<Detail />} />
    </Routes>
  );
}

修改Home组件,移除内部状态,直接使用传入的props:

export default function Home(props: { items: Item[] }) {
  return (
    <main>
      <For each={props.items}>
        {(item) => (
          <A href={`/item/${item.id}`}>{item.name}</A>
        )}
      </For>
    </main>
  );
}

方案2:使用createResource缓存异步数据

SolidJS的createResource专门用于处理异步数据,自带缓存机制。只要请求的依赖项不变,组件重新挂载时不会重复发起请求。

修改Home组件:

import { createResource } from 'solid-js';

export default function Home() {
  // 依赖项设为固定值,确保仅请求一次
  const [items] = createResource(() => true, async () => {
    return await fetchItemsThroughExpensiveAPI();
  });

  return (
    <main>
      {/* 可根据需求添加加载状态提示 */}
      <For each={items() || []}>
        {(item) => (
          <A href={`/item/${item.id}`}>{item.name}</A>
        )}
      </For>
    </main>
  );
}

方案3:手动实现组件缓存(Keep-Alive)

如果需要保留Home组件的实例(比如滚动位置、临时状态),可以手动实现缓存组件避免卸载。

创建KeepAlive组件:

import { createSignal, Show } from 'solid-js';

export default function KeepAlive(props: { children: JSX.Element }) {
  const [cached, setCached] = createSignal<JSX.Element | null>(null);
  setCached(() => props.children);

  return <Show when={cached()}>{cached()}</Show>;
}

在路由中使用:

<Routes>
  <Route path="/" element={<KeepAlive><Home /></KeepAlive>} />
  <Route path="/item/:id" element={<Detail />} />
</Routes>

注意:该方式会让Home组件常驻内存,适合需要保留组件状态的场景,需注意内存占用。


内容的提问来源于stack exchange,提问作者Simon Park

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 20:35:27