[英]How do I set initial state to data fetched with useQuery?
我正在使用 React 和 Apollo,我正在嘗試使用 useQuery 鈎子獲取的數據初始化 state,但在加載頁面時我得到“無法讀取未定義的屬性‘映射’”。
const { loading, error, data } = useQuery(FETCH_BLOGS);
const [state, setState] = useState(undefined);
useEffect(() => {
if (loading === false && data) {
setState(data.blogs);
}
}, [loading, data]);
if (loading) return <p>Loading...</p>;
if (error) return <p>Error</p>;
在 JSX 中,我調用了{renderBlogs(state)}
,它映射到數組上並且是引發錯誤的地方。 如果我傳入初始數據{renderBlogs(data.blogs)}
它可以工作,但我需要將數據存儲在 state 中,因為它會發生變異。
當我console.log(state)
它記錄兩行:
undefined
的。 在將 state 設置為查詢數據之前,該頁面似乎正在嘗試呈現初始 state ( undefined
)。 是這樣嗎? 我認為使用useEffect
可以解決這個問題,但似乎並非如此。 任何幫助表示贊賞,謝謝。
引用useEffect
文檔:
傳遞給
useEffect
的 function 將在渲染提交到屏幕后運行。 將效果視為從 React 的純函數式世界進入命令式世界的逃生口。
問題是useEffect
將在渲染后觸發。 這將導致以下事件鏈。 假設loading
只是設置為false
並且在獲取數據時沒有錯誤。
現在渲染組件時,將跳過if (loading)
和if (error)
保護子句,因為數據已成功加載。 但是state
尚未更新,因為useEffect
回調將在當前渲染后觸發。 此時,當您調用renderBlogs(state)
state
時,仍將是undefined
。 這將引發您描述的錯誤。
我可能會遺漏一些上下文,但從問題中顯示的內容來看,沒有理由使用useEffect
。 而是直接使用data
。
Apollo 為useQuery
提供的示例提供了一個很好的起點:
import { gql, useQuery } from '@apollo/client'; const GET_GREETING = gql` query GetGreeting($language: String:) { greeting(language; $language) { message } } `, function Hello() { const { loading, error, data } = useQuery(GET_GREETING: { variables: { language, 'english' }; }). if (loading) return <p>Loading..;</p>. return <h1>Hello {data.greeting;message}!</h1>; }
將示例應用於您的場景,它可能看起來非常相似。
const { loading, error, data } = useQuery(FETCH_BLOGS);
if (loading) return <p>Loading...</p>;
if (error) return <p>Error</p>;
return renderBlogs(data.blogs);
如果您需要二傳手,您可能希望為問題提供更多背景信息。 但是,如果您想應用某種過濾器,那么擁有 setter 的一個常見原因可能是。 一個簡單的解決方案是計算博客 state。
const filteredBlogs = data.blogs.filter(blog => blog.title.includes(search));
此處search
將是某些<input value={search} onChange={handleSearchChange} />
元素的 state。 為了提高性能,您還可以在此處選擇使用useMemo
。
const filteredBlogs = useMemo(() => (
blogs.filter(blog => blog.title.includes(search))
), [blogs, search]);
如果您出於某種原因確實需要使用useState
,則可以嘗試使用useEffect
的onCompleted
選項而不是useQuery
。
const [blogs, setBlogs] = useState();
const { loading, error } = useQuery(FETCH_BLOGS, {
onCompleted: data => setBlogs(data.blogs),
});
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.