![](/img/trans.png)
[英]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.