如何实现自定义Hook获取Snapshot提案数据并正确返回数据?
问题解决:自定义Hook返回Pending Promise的处理方案
你当前的核心问题是:自定义Hook直接返回了request方法的Promise实例,而React组件无法直接处理这种异步返回值,所以打印出来是Promise{<pending>}。要实现符合React Hooks规范的异步数据获取,必须结合useState和useEffect来管理异步状态。
修改后的完整代码
import { useState, useEffect } from 'react'; import { gql, request } from 'graphql-request'; export const useSnapshotProposals = gql` query Proposals { proposals( first: 20 skip: 0 where: { space_in: ["example.eth"] } orderBy: "created" orderDirection: desc ) { id title body choices start end snapshot state author space { id name } } } `; export const useSnapshotProposalsQuery = () => { // 初始化状态:存数据、加载状态、错误信息 const [data, setData] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { // 封装异步请求函数 const fetchProposals = async () => { try { const result = await request('https://hub.snapshot.org/graphql', useSnapshotProposals); setData(result); } catch (err) { setError(err); } finally { setLoading(false); } }; fetchProposals(); }, []); // 空依赖数组确保请求只在组件挂载时执行一次 return { data, loading, error }; };
组件中使用方式
现在你可以按照预期的方式调用Hook,并处理加载、错误和数据状态:
function ProposalsList() { const { data, loading, error } = useSnapshotProposalsQuery(); if (loading) return <div>加载提案中...</div>; if (error) return <div>请求失败:{error.message}</div>; return ( <div className="proposals-container"> {data?.proposals.map(proposal => ( <div key={proposal.id} className="proposal-card"> <h3>{proposal.title}</h3> <p>发起者:{proposal.author}</p> <p>状态:{proposal.state}</p> </div> ))} </div> ); }
关键修改说明
- 状态管理:用
useState创建三个状态变量,分别存储请求结果、加载状态和错误信息,让组件能感知异步请求的不同阶段。 - 异步执行时机:用
useEffect包裹请求逻辑,确保请求在组件挂载后执行,且仅执行一次(通过空依赖数组)。 - Promise处理:用
async/await语法简化异步代码的可读性,同时通过try/catch/finally处理成功、失败和请求完成的状态更新。
内容的提问来源于stack exchange,提问作者Jan Bo
相关产品推荐
相关产品推荐

