inertiajs / inertia

Inertia.js lets you quickly build modern single-page React, Vue and Svelte apps using classic server-side routing and controllers.
https://inertiajs.com
MIT License
6.3k stars 423 forks source link

Cannot fetch prop value after a partial reload with react #1993

Open girardinsamuel opened 1 day ago

girardinsamuel commented 1 day ago

Version:

Describe the problem:

When using partial reload in a page component in React, I cannot manage to get the updated prop value.

In the following example, products prop is not loaded at initial page load because I am using lazy prop on server side. It initiates a second partial page reload with only products prop. From networking tab, I can see it's working. But I don't know how to fetch this new prop value I get with the partial reload.

Any clue ?

function MyPage () {
  const { products } = usePage().props

  useEffect({
     if (!products) {
          router.reload({ only: ["products"], onSuccess:  () => console.log(products}) // logs undefined
     }
  }, [])

  return {
      <div>...</div>
  }
}

Steps to reproduce:

  1. Create a basic page with a partial reload at component mount
  2. On the server side use LazyProp to avoid loading "products" prop at initial page load
  3. Load the page, observe that's it's working in network tab but in the console products prop is not updated

It might not be a bug but just a misuse on my side...the products value might not be updated because I have destructured it ?

Thank you very much in advance.

girardinsamuel commented 1 day ago

After digging further, it might be the same issue as #1890. Calling router.reload() from useEffect() hook might be the issue here ?

PedroAugustoRamalhoDuarte commented 22 hours ago

@girardinsamuel this is a known issue, I don't know how we can fix that. I think is some small error when setting the currentPage in Inertia React implementation, a hot fix for that is use a setTimeout.

import { useEffect, useState } from "react";
import { router, usePage } from "@inertiajs/react";

function MyPage({ products = [] }) {
  useEffect(() => {
    setTimeout(() => {
      router.reload({ only: ["products"] });
    }, 0);
  }, []);

  return <div>...</div>;
}

More info: