Użycie <Suspense/> do dynamicznego wczytania komponentów

0

Czy ktoś z was korzystał z Suspensa w React 18? Próbuje wykorzystać go w React 18 bez komponentów leniwych, ale coś nie działa. Błędów żadnych w programie nie ma. Jeśli zmienię import tak aby komponent importował się przy pomocy React.lazy to działa poprawnie. Czy może podać ktoś jakiś najprostszy przykład na którym to powinno zadziałać?

Znalazłem w dokumentacji https://reactjs.org/docs/react-api.html coś takiego:

"Suspense lets components “wait” for something before rendering. Today, Suspense only supports one use case: loading components dynamically with React.lazy. In the future, it will support other use cases like data fetching."

Czyżby jednak Suspense w React 18 nie był do końca wdrożony?

1
sajek587 napisał(a):

Próbuje wykorzystać go w React 18 bez komponentów leniwych, ale coś nie działa.

A określenie "coś nie działa", to co to dokładnie oznacza?

0
Riddle napisał(a):
sajek587 napisał(a):

Próbuje wykorzystać go w React 18 bez komponentów leniwych, ale coś nie działa.

A określenie "coś nie działa", to co to dokładnie oznacza?

Nie wyświetla się to co podaje we właściwości fallback, czyli komponent zastępczy np. jakiś spinner czy loading.

1
sajek587 napisał(a):

Nie wyświetla się to co podaje we właściwości fallback, czyli komponent zastępczy np. jakiś spinner czy loading.

No to już dochodzimy do tego co jest nie tak - trzeba było od tego zacząć.

Odpowiedź jest bardzo prosta - pokaż kod.

0

Np. taki przykład wzięty z sandboxa: https://codesandbox.io/s/react-suspense-demo-5uimi

W wersji Reacta 16.6 pojawia się loading, natomiast w przypadku najnowszego Reacta już się nie pojawia po zmianie importów na:

import HomePage from './HomePage';
import AboutPage from './AboutPage';
0
sajek587 napisał(a):

Np. taki przykład wzięty z sandboxa: https://codesandbox.io/s/react-suspense-demo-5uimi

W wersji Reacta 16.6 pojawia się loading, natomiast w przypadku najnowszego Reacta już się nie pojawia po zmianie importów na:

import HomePage from './HomePage';
import AboutPage from './AboutPage';

Pokaż cały kod.

0
Riddle napisał(a):
sajek587 napisał(a):

Np. taki przykład wzięty z sandboxa: https://codesandbox.io/s/react-suspense-demo-5uimi

W wersji Reacta 16.6 pojawia się loading, natomiast w przypadku najnowszego Reacta już się nie pojawia po zmianie importów na:

import HomePage from './HomePage';
import AboutPage from './AboutPage';

Pokaż cały kod.

App.js:

import React, { Suspense } from "react";

import HomePage from './HomePage';
import AboutPage from './AboutPage';

function App() {
  const [page, setPage] = React.useState("home");

  return (
    <div>
      <button onClick={() => setPage("home")}>Home</button>
      <button onClick={() => setPage("about")}>About</button>

      <Suspense fallback={"Loading..."}>
        {page === "home" && <HomePage />}
        {page === "about" && <AboutPage />}
      </Suspense>
    </div>
  );
}

export default App;

AboutPage.js:

import React from "react";

const AboutPage = () => {
  return <h1>About Page</h1>;
};

export default AboutPage;

HomePage.js:

import React from "react";

const HomePage = () => {
  return <h1>Home Page</h1>;
};

export default HomePage;

index.js:

import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
    <App />
);
0

Nie masz w tym kodzie nigdzie dynamic-importów.

0
Riddle napisał(a):

Nie masz w tym kodzie nigdzie dynamic-importów.

Z dynamic importami działa, ale właśnie rozchodzi się o to czy w React 18 Suspense miał działać nawet bez dynamicznych importów ?

0
sajek587 napisał(a):
Riddle napisał(a):

Nie masz w tym kodzie nigdzie dynamic-importów.

Z dynamic importami działa, ale właśnie rozchodzi się o to czy w React 18 Suspense miał działać nawet bez dynamicznych importów ?

A gdzie wyczytałeś taką informacje?

Bo wydaje mi się to skrajnie nieprawdopodobne.

0
Riddle napisał(a):
sajek587 napisał(a):
Riddle napisał(a):

Nie masz w tym kodzie nigdzie dynamic-importów.

Z dynamic importami działa, ale właśnie rozchodzi się o to czy w React 18 Suspense miał działać nawet bez dynamicznych importów ?

A gdzie wyczytałeś taką informacje?

Bo wydaje mi się to skrajnie nieprawdopodobne.

Np. tutaj na filmiku: jest to pokazane. Jako ostatni przykład w filmiku. Tyle, że zapasowy komponent jest wyświetlany w momencie pobierania danych.

Z tego co widzę to Suspense w React 18 zadziała bez dynamicznych importów, ale tylko w połączeniu z niektórymi bibliotekami do pobierania danych z api. Dobrze myślę ?

0
sajek587 napisał(a):

Np. tutaj na filmiku: [...] jest to pokazane. Jako ostatni przykład w filmiku. Tyle, że zapasowy komponent jest wyświetlany w momencie pobierania danych.

Byś otworzył chociaż na sekundę dokumentację Suspense w Reacie i byś się dowiedział: https://beta.reactjs.org/reference/react/Suspense

To jest na prawdę proste, wystarczy:

  1. Otwórz ulubioną szukajkę, np google.com
  2. Wpisz dwa słowa: "React" oraz "Suspense" -> "react suspense"
  3. Kliknij "Szukaj"
  4. Kliknij pierwszy link jaki się pojawi
  5. Czytaj

Cytuję:

Only Suspense-enabled data sources will activate the Suspense component. They include:

  • Data fetching with Suspense-enabled frameworks like Relay and Next.js
  • Lazy-loading component code with lazy

Suspense does not detect when data is fetched inside an Effect or event handler.

The exact way you would load data in the Albums component above depends on your framework. If you use a Suspense-enabled framework, you’ll find the details in its data fetching documentation.

Suspense-enabled data fetching without the use of an opinionated framework is not yet supported. The requirements for implementing a Suspense-enabled data source are unstable and undocumented. An official API for integrating data sources with Suspense will be released in a future version of React.

Co do Twojego filmiku, to ja to widze tak, że zobaczyłeś zwykły import i <Suspense/> więc pomyślałeś, że <Susepsnse/> "działa" ze zwykłymi importami. Tylko że w filmiku gość synchronicznie doładował komponenty (czyli u niego też nie działa), ale susepsne się pojawił bo coś w samym załadowanym komponencie doładowuje dodatkowe dane - czyli gość w komponencie użył Susepnse żeby poczekać na dane w komponencie; a Ty próbujesz czekać na sam komponent. Także gość robi jedno, Ty robisz drugie. Zasadność obu jest... no polemizowałbym.

Tak czy tak, mam nadzieję że pomogłem.

0
Riddle napisał(a):
sajek587 napisał(a):

Np. tutaj na filmiku: [...] jest to pokazane. Jako ostatni przykład w filmiku. Tyle, że zapasowy komponent jest wyświetlany w momencie pobierania danych.

Byś otworzył chociaż na sekundę dokumentację Suspense w Reacie i byś się dowiedział: https://beta.reactjs.org/reference/react/Suspense

To jest na prawdę proste, wystarczy:

  1. Otwórz ulubioną szukajkę, np google.com
  2. Wpisz dwa słowa: "React" oraz "Suspense" -> "react suspense"
  3. Kliknij "Szukaj"
  4. Kliknij pierwszy link jaki się pojawi
  5. Czytaj

Cytuję:

Only Suspense-enabled data sources will activate the Suspense component. They include:

  • Data fetching with Suspense-enabled frameworks like Relay and Next.js
  • Lazy-loading component code with lazy

Suspense does not detect when data is fetched inside an Effect or event handler.

The exact way you would load data in the Albums component above depends on your framework. If you use a Suspense-enabled framework, you’ll find the details in its data fetching documentation.

Suspense-enabled data fetching without the use of an opinionated framework is not yet supported. The requirements for implementing a Suspense-enabled data source are unstable and undocumented. An official API for integrating data sources with Suspense will be released in a future version of React.

Co do Twojego filmiku, to ja to widze tak, że zobaczyłeś zwykły import i <Suspense/> więc pomyślałeś, że <Susepsnse/> "działa" ze zwykłymi importami. Tylko że w filmiku gość synchronicznie doładował komponenty (czyli u niego też nie działa), ale susepsne się pojawił bo coś w samym załadowanym komponencie doładowuje dodatkowe dane - czyli gość w komponencie użył Susepnse żeby poczekać na dane w komponencie; a Ty próbujesz czekać na sam komponent. Także gość robi jedno, Ty robisz drugie. Zasadność obu jest... no polemizowałbym.

Tak czy tak, mam nadzieję że pomogłem.

Do końca nie czaje co napisałeś. Przecież na filmiku nie został użyty import dynamiczny, a mimo to komponent zastępczy jest wykonywany.

0
sajek587 napisał(a):

Do końca nie czaje co napisałeś. Przecież na filmiku nie został użyty import dynamiczny, a mimo to komponent zastępczy jest wykonywany.

Przeczytaj ze zrozumieniem mój post wyżej.

Wyjaśniłem Ci to tutaj:

Riddle napisał(a):

Tylko że w filmiku gość synchronicznie doładował komponenty (czyli u niego też nie działa), ale susepsne się pojawił bo coś w samym załadowanym komponencie doładowuje dodatkowe dane - czyli gość w komponencie użył Susepnse żeby poczekać na dane w komponencie; a Ty próbujesz czekać na sam komponent

Tak czy tak, do tego co próbujesz zrobić - Susepnse się nie nadaje. Jeśli chcesz dynamicznie ładować komponenty, to musisz użyć dynamic importów oraz React.lazy(), nie ma innego wyjścia.

0
Riddle napisał(a):
sajek587 napisał(a):

Do końca nie czaje co napisałeś. Przecież na filmiku nie został użyty import dynamiczny, a mimo to komponent zastępczy jest wykonywany.

Przeczytaj ze zrozumieniem mój post wyżej.

Wyjaśniłem Ci to tutaj:

Riddle napisał(a):

Tylko że w filmiku gość synchronicznie doładował komponenty (czyli u niego też nie działa), ale susepsne się pojawił bo coś w samym załadowanym komponencie doładowuje dodatkowe dane - czyli gość w komponencie użył Susepnse żeby poczekać na dane w komponencie; a Ty próbujesz czekać na sam komponent

Tak czy tak, do tego co próbujesz zrobić - Susepnse się nie nadaje. Jeśli chcesz dynamicznie ładować komponenty, to musisz użyć dynamic importów oraz React.lazy(), nie ma innego wyjścia.

Chodzi Ci o to, że osoba na filmie wykonała request do api? I dlatego Suspense się wykonał, bo czekał na załadowanie tych danych w komponencie ?

0
sajek587 napisał(a):

Chodzi Ci o to, że osoba na filmie wykonała request do api? I dlatego Suspense się wykonał, bo czekał na załadowanie tych danych w komponencie ?

Chodzi o to że Ty próbujesz dynamicznie załadować komponent bez dynamic-importów - i to nie ma prawa działać.
Gość w filmiku synchronicznie wczytał komponent.

0
Riddle napisał(a):
sajek587 napisał(a):

Chodzi Ci o to, że osoba na filmie wykonała request do api? I dlatego Suspense się wykonał, bo czekał na załadowanie tych danych w komponencie ?

Chodzi o to że Ty próbujesz dynamicznie załadować komponent bez dynamic-importów - i to nie ma prawa działać.
Gość w filmiku synchronicznie wczytał komponent.

Co masz na mysli pisząc: "synchronicznie wczytał komponent" ?

0
sajek587 napisał(a):
Riddle napisał(a):
sajek587 napisał(a):

Chodzi Ci o to, że osoba na filmie wykonała request do api? I dlatego Suspense się wykonał, bo czekał na załadowanie tych danych w komponencie ?

Chodzi o to że Ty próbujesz dynamicznie załadować komponent bez dynamic-importów - i to nie ma prawa działać.
Gość w filmiku synchronicznie wczytał komponent.

Co masz na mysli pisząc: "synchronicznie wczytał komponent" ?

Nie dynamicznie.

Umyślałeś sobie że <Suspense/> działa z dynamicznymi komponentami bez React.lazy() i bez dynamic-importów - otóż nie działa; i filmik który pokazałeś również na to nie wskazuje.

Owszem, pojawia się fallback w <Suspense/> na filmiku gościa, ale to nie znaczy że ten suspense czeka na wczytanie komponentu (tak jak Ty sobie to wyobrażasz), bo komponent został już wczytany synchronicznie wcześniej. Na filmiku ten <Suspense/> czeka na wczytanie danych w komponencie.

Nie musisz tego rozumieć, ważne jest to że:

  • Jeśli chcesz wczytać dynamicznie komponent, to MUSISZ użyć dynamic importów oraz React.lazy(), nie ma innego wyjścia.

Jak piszesz import Something from 'something' to w tym momencie ten komponent jest wczytany nie dynamicznie, i nie ważne czy go opakujesz później <Suspense/> czy nie, to to nie zmieni tego w jaki sposób ten komponent jest wczytany.

import React, { Suspense } from "react";

import HomePage from './HomePage';      // tutaj, komponent jest wczytany synchronicznie i masz po zawodach
import AboutPage from './AboutPage';    // już nie zamienisz tego na dynamic import

function App() {
  const [page, setPage] = React.useState("home");

  return (
    <div>
      <button onClick={() => setPage("home")}>Home</button>
      <button onClick={() => setPage("about")}>About</button>

      <Suspense fallback={"Loading..."}>
        {page === "home" && <HomePage />}  { /* tutaj <HomePage/> jest już wczytany */ }
        {page === "about" && <AboutPage />}
      </Suspense>
    </div>
  );
}

export default App;
0

Czyli Suspense po stronie klienta we wcześniejszej wersji Reacta 17 działa tak samo jak teraz w React 18 ?

0
sajek587 napisał(a):

Czyli Suspense po stronie klienta we wcześniejszej wersji Reacta 17 działa tak samo jak teraz w React 18 ?

Nie wiem, ale filmik który podesłałeś na pewno na to nie wskazuje.

Możliwe że jest sposób żeby użyć <Suspense/> bez dynamic importów o którym nie wiem, ale na pewno Twój kod, oraz kod gościa który podesłałeś w filmiku na to nie wskazuje.

Przeczytaj changelog React 18: https://reactjs.org/blog/2022/03/29/react-v18.html i poszukaj tam wzmianki o tym, o czym mówisz.

Cytat:

Suspense makes the “UI loading state” a first-class declarative concept in the React programming model. This lets us build higher-level features on top of it.

We introduced a limited version of Suspense several years ago. However, the only supported use case was code splitting with React.lazy, and it wasn’t supported at all when rendering on the server.

In React 18, we’ve added support for Suspense on the server and expanded its capabilities using concurrent rendering features.

Suspense in React 18 works best when combined with the transition API. If you suspend during a transition, React will prevent already-visible content from being replaced by a fallback. Instead, React will delay the render until enough data has loaded to prevent a bad loading state.

Masz nawet napisane For more, see the RFC for Suspense in React 18., wejdź sobie w ten link: https://github.com/reactjs/rfcs/blob/main/text/0213-suspense-in-react-18.md i przeczytaj dokładnie co <Suspense/> może i nie może.

0

Czyli React (nie używam, kiedyś zacząłem, ale później przerwałem naukę) jest tak ograniczony, że np. zrobienie pokazywania komunikatu "trwa ładowanie danych" lub czegoś podobnego takiego jak ikona ładowania na czas wykonywania żądania AJAX lub fetch jest rzeczą prawie niemożliwą, wymagająca znajomości jakichś rzadko używanych sposobów importowania?

W jQuery albo czystym JS nie ma z czymś takim żadnego problemu.

0
valdemar napisał(a):

Czyli React (nie używam, kiedyś zacząłem, ale później przerwałem naukę) jest tak ograniczony, że np. zrobienie pokazywania komunikatu "trwa ładowanie danych" lub czegoś podobnego takiego jak ikona ładowania na czas wykonywania żądania AJAX lub fetch jest rzeczą prawie niemożliwą, wymagająca znajomości jakichś rzadko używanych sposobów importowania?

W jQuery albo czystym JS nie ma z czymś takim żadnego problemu.

Ładowanie danych jest banalne, i pokazywanie loadera również.

Ale w temacie nie chodzi o ładowanie danych, tylko autor pyta o dynamiczne wczytywanie komponentów. I to też jest dosyć proste, wystarczy użyć React.lazy().

1 użytkowników online, w tym zalogowanych: 0, gości: 1