1

I am trying to make the data fetched with axios and react-query available to my components using Context API, but axios.get() doesn't seem to work. I get no GET request on the server-side and the data returned by axios is undefined.

kitDataContext.js

Here I tried to console.log() the data returned by axios.get() and it prints undefined on the console:

import { useQuery } from '@tanstack/react-query'
import axios from 'axios'
import { createContext } from 'react';

export const kitsDataContext = createContext();

//creates provider so content on the DB can be accessible to all components
export const KitsDataProvider = ({children}) => {

    const fetchKits = () =>{
        return axios.get("http://localhost:5001/kitsDB");
    };

    //saves JSON data on "data" variable
    function RQKitsDB(){
        const { isLoading, data } = useQuery("kitsDB", fetchKits);

        //prints undefined...
        console.log(data);
        return { data };
    };

    return( 
        <kitsDataContext.Provider value={{RQKitsDB}}>
            {children}
        </kitsDataContext.Provider>
    );  
};

SerumRow.js

This is the only component I'll be using the data for now, I didn't make anything with the data yet, just made the context available for the component so far. Note that I am also wrapping this component with the required providers so I can simplify my rendering on index.js.

import "./row.css"
import {Button} from 'react-bootstrap';
import AddToCart from './AddToCart.js';

import { useContext } from 'react';
import { kitsDataContext } from './contexts/kitsDataContext.js'

import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { KitsDataProvider } from './contexts/kitsDataContext.js'

const queryClient = new QueryClient()

//complete row with all the data from database, also adds AddToCart button below every kit
function SerumRowNoProviders() {

  const { RQKitsDB } = useContext(kitsDataContext);
  const { data } = RQKitsDB;

  return (
    
      <div className="small-container">
        <h1>SERUM PRESETS</h1>
        <div className="row">
          <div className="col-3 text-center">
            <img src="./images/WavSupply-Sidepce-Elysium-Loop-Kit-920x920.jpg" alt="Product 1" />
            <div></div>
            <div className="priceReact"></div>
            <AddToCart />
          </div>
          <div className="col-3 text-center">
            <img src="./images/WavSupply-Sidepce-Elysium-Loop-Kit-920x920.jpg" alt="Product 2" />
            <div></div>
            <div className="priceReact"></div>
            <AddToCart />
          </div>
          <div className="col-3 text-center">
            <img src="./images/WavSupply-Sidepce-Elysium-Loop-Kit-920x920.jpg" alt="Product 3" />
            <div></div>
            <div className="priceReact"></div>
            <AddToCart />
          </div>
          <div className="col-3 text-center">
            <img src="./images/WavSupply-Sidepce-Elysium-Loop-Kit-920x920.jpg" alt="Product 4" />
            <div></div>
            <div className="priceReact"></div>
            <AddToCart />
          </div>
        </div>
        {/*takes user to page with all avaliable kits */}
        <h1><button type="button" id="show-more" className="btn btn-outline-dark btn-lg">BROWSE ALL</button></h1>
      </div>
  );
}

//wraps SerumRowNoProviders() with needed Providers
function SerumRow() {
  return (
    <QueryClientProvider client={queryClient}>
      <KitsDataProvider>
        <SerumRowNoProviders />
      </KitsDataProvider>
    </QueryClientProvider>
  );
}

export default SerumRow;

index.js

Here I am simply rendering the component:

const serumRow = document.getElementById("SerumRow");
root = ReactDOM.createRoot(serumRow);
root.render(
  <React.StrictMode>
        <SerumRow />
  </React.StrictMode>
  );

/kitsDB route

This is the server route for /kitsDB, it prints "request!" when I access it with the browser but not when I run the script I showed above:

app.get("/kitsDB", async (req,res) => {
    //returns all kits from DB organized by newest first
    const result = await Kits.find().sort({_id:-1});
    res.send({"aa" : result});
    console.log("request!");
});

I tried using axios.get() outside of the context on that same route and everything worked fine, so the issue must be the way I am using context. I am quite new to React and I can't see exactly what is wrong. I humbly ask for any help you can give me.

poltergaz
  • 27
  • 5
  • Does this answer your question? [React-Query: How to useQuery when button is clicked](https://stackoverflow.com/q/62340697/283366). If not, it's not clear why you've wrapped `useFetch()` within the `RQKitsDB()` function – Phil Aug 12 '23 at 01:36

2 Answers2

1

You are not allowed to put hooks (such as useQuery) inside custom functions (such as RQKitsDB), it needs to be placed in the top level of the component.

export const KitsDataProvider = ({children}) => {

    const fetchKits = () =>{
        return axios.get("http://localhost:5001/kitsDB");
    };
    
    // put useQuery in top level of component
    const { isLoading, data } = useQuery("kitsDB", fetchKits);

    return( 
        <kitsDataContext.Provider value={{data}}>
            {children}
        </kitsDataContext.Provider>
    );  
};

Now data can be accessed like this

const { data } = useContext(kitsDataContext);
Anton
  • 1,045
  • 1
  • 7
  • 16
  • Thanks for your help but I'm still having the same issue. I'm pretty sure the issue is the axios.get() because it is not making the get request. – poltergaz Aug 15 '23 at 16:19
0
const { isLoading, data } = useQuery(["kitsDB"], () => fetchKits());

I fixed the problem changing that useQuery line. I think what made it work was evoking fetchKits() instead of just passing it as fetchKits. Not sure why since everybody I came across suggested not evoking functions when passing them as arguments but well, if it works, it works.

poltergaz
  • 27
  • 5