[英]useReducer passed with useContext but a child component displays empty state.map
[英]no data is passed into state when using useContext/useReducer together with useQuery
export const itemReducer = (state, action) => {
switch (action.type) {
default:
return state
}
}
import React, { useState, useReducer, createContext, useContext } from 'react'
import { useQuery } from '@apollo/client'
import { CURRENT_MONTH_BY_USER } from '../graphql/queries'
import { itemReducer } from '../reducers/ItemReducer'
const Items = createContext()
export const ItemProvider = ({ children }) => {
let items = []
const [state, dispatch] = useReducer(itemReducer, { items: items })
const result = useQuery(CURRENT_MONTH_BY_USER)
if (result.data && result.data.getCurrentMonthByUser) {
items = [...result.data.getCurrentMonthByUser]
}
return <Items.Provider value={{ state, dispatch }}>{children}</Items.Provider>
}
export const ItemsState = () => {
return useContext(Items)
}
export default ItemProvider
let items
從useQuery獲取正確的數據,但是沒有任何內容傳遞到 state,因此我無法將數據從上下文傳輸到另一個組件。 我在這里做錯了什么?
在調試items
和state
時,由於加載,它們最初是空的,但是只有items
接收到正確的數據,而 state 仍然是空數組。
如果我將 static 數據放入let items
,它就可以正常工作,所以我的useQuery也可能有問題嗎?
如果您查看items
的使用位置,就很容易看出您的問題。 這只是您的useReducer
調用的初始 state - 但在此之后items
僅設置為非空值。 這對組件絕對沒有影響,因為以后不會在您的組件 function 中使用items
,並且初始 state 僅在第一次渲染時設置一次。
要解決這個問題,您需要接受 reducer 的使用,添加一個新的操作類型來設置此初始數據,然后在您擁有數據時分派它。 所以在你的減速器中添加這樣的東西:
export const itemReducer = (state, action) => {
switch (action.type) {
case SET_INITIAL_DATA: // only a suggestion for the name, and obviously you need to define this as a constant
return { ...state, items: action.items };
/* other actions here */
default:
return state
}
}
然后像這樣重寫你的組件:
export const ItemProvider = ({ children }) => {
const [state, dispatch] = useReducer(itemReducer, { items: [] })
const result = useQuery(CURRENT_MONTH_BY_USER)
if (result.data && result.data.getCurrentMonthByUser) {
dispatch({ type: SET_INITIAL_DATA, items: result.data.getCurrentMonthByUser });
}
return <Items.Provider value={{ state, dispatch }}>{children}</Items.Provider>
}
此外,雖然這與您的問題無關,但我會注意到您的ItemsState
導出似乎是一個自定義掛鈎(它不能是其他任何東西,因為它不是一個組件而是使用一個掛鈎) - 這很好但是有是 React 中一個非常嚴格的約定,所有自定義鈎子的名稱都采用useXXX
形式,我強烈建議您遵循該約定。 因此,您可以將其重命名為useItemsState
(我更喜歡useItemsContext
以明確它只是一個專門針對您的特定上下文的useContext
掛鈎)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.