如何在SolidJS组件返回JSX前访问已获取的资源数据?
解决SolidJS中异步资源加载后的处理问题
问题根源
你在点击事件里同步调用user()时,createResource发起的异步请求还未完成,所以初始返回undefined,自然无法读取name属性。SolidJS的createResource是响应式异步资源,不能像同步函数那样直接获取返回值,必须利用其响应式特性处理加载完成后的逻辑。
优雅解决方案
不用setTimeout,我们可以通过响应式信号触发资源请求+监听资源变化的方式处理:
- 用
createSignal存储登录参数,触发资源的异步请求 - 让
createResource依赖这个信号,参数变化时自动发起请求 - 用
createEffect监听资源状态,数据加载完成后执行处理逻辑
修改后的代码示例:
import { createSignal, createResource, createEffect } from 'solid-js'; import MD5 from 'your-md5-library'; // 替换为你的MD5库 const fetchData = async url => { // 注意:原代码里的`this.path`在组件外可能无法访问,建议改为全局常量或传入 const results = await fetch(`/your-base-path/${url}`); // 替换实际基础路径 return await results.json(); }; function User() { // 存储登录参数的信号,初始为null表示未发起请求 const [signInParams, setSignInParams] = createSignal(null); // 依赖signInParams的资源,参数存在时发起请求 const [user] = createResource(signInParams, async (params) => { if (!params) return null; return fetchData(`json/sign-in/${params.email}/${MD5(params.password)}`); }); // 监听资源变化,数据加载完成后执行逻辑 createEffect(() => { const userData = user(); // 排除加载中状态,确保拿到完整数据 if (userData && !user.loading) { console.log(userData.name); // 在这里编写数据加载完成后的处理逻辑,比如存储到本地、跳转页面等 } }); const handleSubmit = e => { e.preventDefault(); signIn({ email: "Foo", password: "Bar" }); }; const signIn = obj => { if (obj.email && obj.password) { // 设置参数触发资源请求 setSignInParams(obj); } }; return ( <> {/* 可以根据资源状态展示加载或错误提示 */} {user.loading && <div>登录中...</div>} {user.error && <div>登录失败:{user.error.message}</div>} <button onClick={handleSubmit}>Sign In</button> </> ); } export default User;
关键说明
- 资源的响应式特性:
createResource会自动跟踪依赖的信号(signInParams),当参数变化时重新发起请求 - 状态访问:可以通过
user.loading判断是否在加载中,user.error捕获请求错误,user()获取返回数据 createEffect的作用:它会在响应式依赖(这里是user资源)变化时自动执行,确保只在数据加载完成后处理逻辑
内容的提问来源于stack exchange,提问作者David Apple
相关产品推荐
相关产品推荐

