React-query: `onSuccess` should be called before populating `data`

Created on 23 Apr 2020  路  6Comments  路  Source: tannerlinsley/react-query

Currently, onSuccess is allowed to return something, that will populate data. However, this happens after the first population, making the application to fickler when this happen the first time.

Ideally, onSuccess should be called before populating data, or maybe have a "transform" method with this behavior.

Most helpful comment

No, because what you are doing is actually mutating the data reference, not replacing it. Array.prototype.reverse() does not create a new array, it reverses the order of the existing array in place.

All 6 comments

  • Are you talking about the onSuccess option of useQuery or useMutation? They both have one.
  • In useQuery, the query data is set before onSuccess is called, in useMutation, the mutation data is set after the onSuccess async flow.
  • In useQuery, onSuccess is not an async function and will not delay any execution. It's merely to be notified of a successful call. In useMutation, the return value of onSuccess is a promise that is merely used for async flow.
  • In both useQuery and useMutation, onSuccess does not set or override any values when returned

Also, since there is no reproduction case or any example for me to reproduce this with, I'm going to close this issue. Feel free to open a new one that follows the issue template instructions.

Which template instructions? There isn't any.

I create a simple Stackblitz with a reproducible scenario. It's happening randomly after a success fetching.

https://stackblitz.com/edit/react-query-on-success-issue?file=index.js

Oh sorry, it looks like the issue template isn't working right now. My bad.

So looking at your example, I see what you're trying to do. By design, none of the side effect handlers can mutate or change the data after the query function succeeds. if you need to do any data manipulation, please do it in your queryFn:

import React, { useEffect, Fragment } from "react";
import { render } from "react-dom";
import { useQuery } from "react-query";

import Hello from "./Hello";
import "./style.css";

const App = () => {
  const { data = [], status } = useQuery({
    queryKey: "todos",
    queryFn: () =>
      fetch("https://jsonplaceholder.typicode.com/posts?_limit=5").then(res =>
        res.json().reverse()
      ),
    config: {
      onSuccess: (data) => console.log(data),
    }
  });

  return (
    <div>
      <Hello name={"world"} />
      <p>Start editing to see some magic happen :)</p>
      {data.map(({ body, title }, index) => (
        <div key={index}>
          <h3>{title}</h3>
          <p> {body}</p>
        </div>
      ))}
    </div>
  );
};

render(<App />, document.getElementById("root"));

But the returning data from the onSuccess is working. Should this be filled as a bug then?

No, because what you are doing is actually mutating the data reference, not replacing it. Array.prototype.reverse() does not create a new array, it reverses the order of the existing array in place.

Was this page helpful?
0 / 5 - 0 ratings