TanStack / TanStack/query

broadcastQueryClient doesn't keep cache between tabs

Open
#2,142 10 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

package: broadcast-client
Dominant language
TypeScript
Stars
50.3k
Forks
4.2k
Avg merge
18h 25m
Merged PRs (30d)
200

Description

Describe the bug
I'm trying broadcastQueryClient feature to make the cache persist across tabs. When opening a new tab, the server endpoint is called, while react-query should prevent this and return the cache data instead.

My usecase:
When the app mounts, I make an api call to retrieve the user's info and store them in a global state. There are sensitive informations, so local-storage is not an option. I have a search result page. Users open a new tab each time they click on a product. Each new tab remounts the whole app, and the /get-user-infos route is called repeatedly. I need to cache the result across tabs.

To Reproduce
index.js

import { QueryClient, QueryClientProvider } from "react-query";
import { broadcastQueryClient } from "react-query/broadcastQueryClient-experimental";

const queryClient = new QueryClient();
broadcastQueryClient({
  queryClient,
  broadcastChannel: "myapp",
});

ReactDOM.render(
  <QueryClientProvider client={queryClient}>
    <App />
  </QueryClientProvider>,
  document.getElementById("root")
);

App.js

export default function App() {
  const { user, loading } = getUserInfos();
  return (
    <BrowserRouter>
      {loading ? "loading..." : <div>hello {user.name}! </div>}
      <Switch>
        <Route to="/" render={Home} />
        <Route to="/user" render={User} />
      </Switch>
    </BrowserRouter>
  );
}

service.js (where the api cal is made)

/* eslint-disable react-hooks/rules-of-hooks */
import { useQuery } from "react-query";
import { api } from "./config";

const _getUserInfos = async () => {
  try {
    const res = api.get("/get-user-infos");
    return res;
  } catch (err) {
    return err;
  }
};

export const getUserInfos = () => {
  const { data, isLoading } = useQuery("contact", () => _getUserInfos(), {
    staleTime: 1000 * 60 * 60 * 24, // 24 hours
    cacheTime: 1000 * 60 * 60 * 24, // 24 hours
  });
  return { user: data && data.data.user, loading: isLoading };
};

The new tab is open like this on <Home/>

  const onOpen = () => {
    const tab = window.open("/user");
    tab.focus();
  };

The cache works fine as long as I use react-router-dom on the same page.

The server:

const app = require("express")();
const cors = require("cors");

app.use(cors({ credentials: true, origin: ["http://localhost:3000"] }));

app.listen(8000, () => console.log(`server is listening on port 8000!`));

app.get("/get-user-infos", (req, res) => {
  console.log("login route called!");
  res.status(200).json({
    user: {
      name: "joe",
      _id: "1234",
    },
  });
});

Expected behavior
React-query returns the cache for /get-user-infos when opening a new tab.

Desktop (please complete the following information):

  • OS: osx
  • Browser: chrome

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start at the broadcastQueryClient entry point imported from react-query/broadcastQueryClient-experimental and reproduce the two-tab setup with the contact query and 24-hour stale and cache times. Trace whether the new tab receives the existing query before its initial fetch. Done means opening /user in a new tab returns the broadcast cache without calling /get-user-infos.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, react
Domain
frontend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.