Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

136
Views
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. 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.

If i put static data into let items it works just fine, so maybe there can be something wrong with my useQuery as well?

about 4 years ago · Juan Pablo Isaza
1 answers
Answer question

0

It's easy to see your problem if you look at where items is used. That's only as the initial state to your useReducer call - but items is only set to a non-empty value after this. 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.

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. 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. 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).

about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!