question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Cannot get react-query (useQuery hook) to work with Storybook with external API

See original GitHub issue

I am using storybook to develop my react components in isolation. I am running into an issue with using react-query (useQuery) with storybook. Implementing the component in the app, I get no errors and things work as expected.

async function searchStationsByCallLetter(_, param) {
  const request = {
    callLettersView: param, 
  };

  const { data } = await ApiService().makeApiCall(API_ENDPOINTS.BROADCAST_LINEUP.SEARCH_STATIONS, request, HTTP_POST);
  return data;
}

export default function useSearchStationsByCallLetter(inputValue = '') {
  return useQuery(['searchStationsByCallLetter', inputValue], searchStationsByCallLetter);

I have a custom react hook useSearchStationsByCallLetter that returns the useQuery hook. React-query should be using searchStationsByCallLetter as the api call. ApiService and makeApiCall are a custom axios setup.

The error I get in storybook is:

TypeError: Object(...) is not a function
    at _callee$ (AddLineupHooks.js:8)
    at tryCatch (runtime.js:63)
    at Generator.invoke [as _invoke] (runtime.js:293)
    at Generator.next (runtime.js:118)
    at asyncGeneratorStep (asyncToGenerator.js:3)
    at _next (asyncToGenerator.js:25)
    at asyncToGenerator.js:32
    at new Promise (<anonymous>)
    at Object.<anonymous> (asyncToGenerator.js:21)
    at Object.searchStationsByCallLetter [as queryFn] (AddLineupHooks.js:8)

Desktop (please complete the following information):

  • OS: Mac
  • Browser: chrome
  • Version: latests

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:7 (2 by maintainers)

github_iconTop GitHub Comments

31reactions
jonniebigodescommented, Oct 2, 2020

@sdivelbiss i’ve kept track of your issue while i was working on getting Storybook and React Query working nicely with Axios.

Here’s what i did:

  • Created a new React app with create-react-app.
  • Installed Storybook, react-query, react-query-devtools, axios and msw (mock service worker) for testing purposes.
  • Changed .storybook/preview.js to the following to allow react-query cache provider,the react-query-devtools and my mock service working with Storybook:
import React from 'react'

import { ReactQueryCacheProvider, QueryCache } from "react-query";
import { ReactQueryDevtools } from "react-query-devtools";

const queryCache = new QueryCache();

export const parameters = {
  actions: { argTypesRegex: "^on[A-Z].*" },
};
/**
 * adds a Storybook decorator to get the cache and dev tools showing for each story
 */
export const decorators=[
  (story) => (
    <ReactQueryCacheProvider queryCache={queryCache}>
      {story()}
      <ReactQueryDevtools />
    </ReactQueryCacheProvider>
  ),
]
// get the mocked handlers (endpoints) and starts the service worker
if (typeof global.process === 'undefined') {
  const { worker } = require("../src/mocks/workers");
  worker.start();
}
  • Created a barebones component for the use-query with the following code:
import React from "react";
import Axios from "axios";
import { useQuery } from "react-query";
/**
 * Component to demonstrate how to mock data (GET request) with react-query and axios
 * 
 */
const AxiosRestExample = () => {
  // use query to fetch something with axios out of the url (this case a mocked one)
  const { data, error, isLoading } = useQuery("rest-ricky", async () => {
    const { data } = await Axios.get("/ricky-rest");
    return data;
  });
  if (isLoading) return <h1>Loading...Go grab a coffee</h1>;
  if (error) {
    return (
      <>
        <h2>Upsy daisy something went wrong</h2>
        <h2>{error.message}</h2>
      </>
    );
  }
  return (
    <div>
      <h1>{data.name}</h1>
      <p>{data.description}</p>
    </div>
  );
};

export default AxiosRestExample;
  • Created a file called AxiosRestExample.stories.js with the following:
import React from "react";
import AxiosRestExample from "./AxiosRestExample";

export default {
  title: "React Query Rest (AXIOS) GET Example",
  component: AxiosRestExample,
};

const Template = (args) => <AxiosRestExample {...args} />;

export const Default = Template.bind();
  • To test out a POST method i’ve created one more component called AxiosRestPostExample.js with the following:
import React, { useState } from "react";
import Axios from "axios";
import { useMutation } from "react-query";
import PropTypes from "prop-types";

/**
 * function to send something to the url
 * @param {String} textValue
 */
async function SendMessage({ textValue }) {
  try {
    const { data } = await Axios.post("/ricky-post", {
      item: textValue,
    });
    return data;
  } catch (error) {
    console.log(`SEND MESSAGE ERROR:${error}`);
  }
}

/**
 * Component to demonstrate how to mock data (POST request) with react-query and axios
 * @param {String} initialvalue a dummy prop for the component 
 */
const AxiosRestPostExample = ({ initialvalue }) => {
  const [textValue, setTextValue] = useState(initialvalue);

  const [mutate, { status, error }] = useMutation(SendMessage, {
    onSuccess: () => {
      console.log("POSTED SOMETHING");
    },
    onError: () => {
      console.log(`SOMETHING WENT WRONG:\n${error}`);
    },
  });
  return (
    <div>
      <input value={textValue} onChange={(e) => setTextValue(e.target.value)} />
      <button
        onClick={() => mutate({ textValue })}
        disabled={status === "loading" || !textValue}
      >
        Post something
      </button>
    </div>
  );
};
AxiosRestPostExample.propTypes = {
  initialvalue: PropTypes.string,
};
AxiosRestPostExample.defaultProps = {
  initialvalue: "Ricky Sanchez",
};

export default AxiosRestPostExample;

  • Included a stories file for this component as well called AxiosRestPostExample.stories.js:
import React from "react";
import AxiosRestPostExample from "./AxiosRestPostExample";

export default {
  component: AxiosRestPostExample,
  title: " React Query Rest Post Example with Axios",
};

const Template = (args) => <AxiosRestPostExample {...args} />;

export const Default = Template.bind({});

export const WithRandomItem = Template.bind({});
WithRandomItem.args = {
  initialvalue: "Oingo Boingo",
};
  • Configured msw by adding two files :
    • src/mocks/server with the following inside:
import { setupWorker } from 'msw'
import { handlers } from './handlers'
// This configures a Service Worker with the given request handlers.
export const worker = setupWorker(...handlers)
  • src/mocks/handlers with the following:
import { rest } from "msw";
/**
 * a list of handlers (endpoints) to emulate (mock) a actual implementation
 */
export const handlers = [
  rest.get("/ricky-rest", (req, res, ctx) => {
    return res(
      ctx.status(200),
      ctx.json({
        name: "Rick Sanchez",
        description: "Scientist extraordinaire",
      })
    );
  }),
  rest.post("/ricky-post", (req, res, ctx) => {
    const {item}= req.body
    return res(
      ctx.status(200),
      ctx.json({
        message: `hey hey ${item}`,
      })
    );
  }),
];
  • Issued yarn storybook and i get the following:
    • The GET request (use-query): Storybook-React-Query-get
  • And from the POST component story i get the following: Storybook-React-Query-POST Storybook-React-Query-Use-Mutation-POST-DEVTOOLS

I know that this is a rather small and possibly skewed approach to the problem. But it seems that Storybook and React-Query will work fine together.

If you can provide additional information about how you’re implementing the associated story file and how you’ve setup Axios we could take a look at it and probably provide you with a more concrete answer.

Or i can hoist up this small reproduction to a repo and you can take a look at it in your time. Let us know and we’ll move from there.

Stay safe

1reaction
Arahiscommented, Dec 6, 2022

Maybe my question is not exactly regards this topic, but may be someone can answer. The case when I need to show only the loading state from react-query, what should I do in this case?

Read more comments on GitHub >

github_iconTop Results From Across the Web

Cannot get react-query (useQuery hook) to work ... - Issuehunt
I have a custom react hook useSearchStationsByCallLetter that returns the useQuery hook. React-query should be using searchStationsByCallLetter as the api call.
Read more >
Use react-query (useQuery) with Storybook getting error
I have a custom react hook useSearchStationsByCallLetter that returns the useQuery hook. React-query should be using searchStationsByCallLetter ...
Read more >
Testing React components - Apollo GraphQL Docs
This article describes best practices for testing React components that use Apollo Client. The examples below use Jest and React Testing Library, ...
Read more >
React Query 3: A Guide to Fetching and Managing Data
Need to fetch data in React? Learn about React Query, an excellent server state management library for simplifying your data-fetching needs.
Read more >
Top 5 react-query Code Examples - Snyk
To help you get started, we've selected a few react-query examples, based on popular ways it is used in public projects. Secure your...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found