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

SolidJs:如何通过createResource触发createEffect更新signal

解决createEffect无法捕获createResource返回值的问题

以下是导致你问题的核心原因及修正方案:

问题分析

  • createResource源参数非响应式:你直接传递params.id作为资源的依赖,但SolidJS要求createResource的第一个参数是响应式访问器(函数),否则只会初始化执行一次,无法监听params.id的变化。
  • loading状态访问错误:userDetailsData.loading是响应式信号,必须通过userDetailsData.loading()调用获取当前状态,直接访问属性无法拿到实时值。
  • 错误处理掩盖数据:API请求的catch块捕获错误后返回undefined,导致createResource的data变为undefined,同时错误信息被隐藏,无法触发后续的更新逻辑。
  • 模板插值错误:<span>userDetails().id</span>只会渲染字符串,需要用{}包裹表达式才能渲染变量值。

修正后的代码

class UserDetails {
    constructor(
        public id: string,
        public name: string,
        public age: number,
        public email: string,
    ){}
}

const emptyUserDetails = (): UserDetails => ({
    id: '1234',
    name: 'Test User',
    age: 0,
    email: 'testUser@email.com',
});

const loadUserDetailsFromAPI = async(businessId: string) => {
    const res = await fetch(`users-URl/${businessId}`, {
        method: 'GET',
    });
    
    if (!res.ok) {
        throw new Error(res.statusText);
    }
    
    return res.json() as Promise<UserDetails>;
}

export default function UsersPage() {
    const params = useParams();

    const [userDetails, setUserDetails] = createSignal<UserDetails>(emptyUserDetails());
    // 改用响应式访问器作为资源依赖
    const [userDetailsData] = createResource(() => params.id, loadUserDetailsFromAPI);

    createEffect(() => {
        const data = userDetailsData();
        const isLoading = userDetailsData.loading();
        
        console.log(data, isLoading);

        if (data && !isLoading) {
            setUserDetails(data);
        }
    });

    return (
        <div class="flex flex-col gap-3">
            <span>{userDetails().id}</span>
            <span>{userDetails().name}</span>
            <span>{userDetails().age}</span>
            <span>{userDetails().email}</span>
        </div>
    );
}

额外优化建议

在SolidJS中,你可以直接使用createResource返回的状态,无需额外维护signal,简化代码:

return (
    <div class="flex flex-col gap-3">
        {userDetailsData.loading() ? <span>加载中...</span> : (
            <>
                <span>{userDetailsData()?.id}</span>
                <span>{userDetailsData()?.name}</span>
                <span>{userDetailsData()?.age}</span>
                <span>{userDetailsData()?.email}</span>
            </>
        )}
        {userDetailsData.error() && <span>加载失败:{userDetailsData.error()?.message}</span>}
    </div>
);

内容的提问来源于stack exchange,提问作者Carlo Nyte

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 05:43:12