简体   繁体   English

将 useContext/useReducer 与 useQuery 一起使用时,没有数据传递到 state

[英]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 gets correct data from the useQuery , however nothing is passed into the state, therefore I am unable to transfer data into another components from the context. let itemsuseQuery获取正确的数据,但是没有任何内容传递到 state,因此我无法将数据从上下文传输到另一个组件。 What am I doing wrong here?我在这里做错了什么?

When debugging both items and state they're initially empty because of the loading however then only the items receives correct data and state remains as empty array.在调试itemsstate时,由于加载,它们最初是空的,但是只有items接收到正确的数据,而 state 仍然是空数组。

If i put static data into let items it works just fine, so maybe there can be something wrong with my useQuery as well?如果我将 static 数据放入let items ,它就可以正常工作,所以我的useQuery也可能有问题吗?

It's easy to see your problem if you look at where items is used.如果您查看items的使用位置,就很容易看出您的问题。 That's only as the initial state to your useReducer call - but items is only set to a non-empty value after this.这只是您的useReducer调用的初始 state - 但在此之后items仅设置为非空值。 That has absolutely no effect on the component, because items is not used later in your component function, and the initial state is only ever set once, on the first render.这对组件绝对没有影响,因为以后不会在您的组件 function 中使用items ,并且初始 state 仅在第一次渲染时设置一次。

To solve this you need to embrace your use of a reducer, adding a new action type to set this initial data, and then dispatching that when you have the data.要解决这个问题,您需要接受 reducer 的使用,添加一个新的操作类型来设置此初始数据,然后在您拥有数据时分派它。 So add something like this to your 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
  }
}

and then rewrite your component like this:然后像这样重写你的组件:

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>
}

Also, while this is unrelated to your question, I will note that your ItemsState export appears to be a custom hook (it can't be anything else since it isn't a component but uses a hook) - that is perfectly fine but there is a very strong convention in React that all custom hooks have names of the form useXXX , which I strongly suggest you should follow.此外,虽然这与您的问题无关,但我会注意到您的ItemsState导出似乎是一个自定义挂钩(它不能是其他任何东西,因为它不是一个组件而是使用一个挂钩) - 这很好但是有是 React 中一个非常严格的约定,所有自定义钩子的名称都采用useXXX形式,我强烈建议您遵循该约定。 So you could rename this something like useItemsState (I would prefer useItemsContext to make clear it's just a useContext hook specialised to your specific context).因此,您可以将其重命名为useItemsState (我更喜欢useItemsContext以明确它只是一个专门针对您的特定上下文的useContext挂钩)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 useReducer 与 useContext 一起传递,但子组件显示空 state.map - useReducer passed with useContext but a child component displays empty state.map 使用 React useContext 和 useReducer 时出现打字稿错误 - Typescript error when using React useContext and useReducer 在反应中将 useReducer 与 useContext 一起使用时未定义“调度” - 'dispatch' is not defined when using useReducer with useContext in react 使用带有自定义钩子的 useContext 与 useContext + useReducer - using useContext with custom hooks vs useContext + useReducer State 使用 useContext 时不更新 - State not updating when using useContext 反应 useContext useReducer state 挂钩错误 - React useContext useReducer state Hooks Error 如何在 useReducer() 和 useContext() state 管理设置中使用 useEffect() 从 api 获取数据? - How to use useEffect() to fetch data from an api in a useReducer() and useContext() state management setup? React useContext &amp; useReducer - 在应用程序中需要全局状态,对使用一个和多个 reducer 感到困惑 - React useContext & useReducer - Need global state in app, confused about using one vs multiple reducers 在 NextJS 中使用 useContext 和 useReducer 并将 null 作为上下文读取 - Using useContext and useReducer in NextJS and reading null as context 关于使用 useContext 和 useReducer 钩子的问题 - Question around using useContext and useReducer hooks
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM