Skocz do zawartości
Szukaj na Pecetowiczu
  • Utwórz konto

Definiowanie danych początkowych za pomocą react-query


Rekomendowane odpowiedzi

Cześć wszystkim, dla zabawy postanowiłem użyć react-query do uzupełnienia danych w landing page.  Problem jest w tym, że chciałbym przesyłać je (za pomocą propsów) do odpowiednich sekcji, więc zależy mi na odpowiednim typowaniu. Niestety, gdy ustawiam parametr initialData na pusty obiekt, to nie działa fetchowanie. W przeciwnym wypadku, wszystko jest ok z tym, że zmienna jest zdefiniowana jako SectionsType | undefined - czego nie chcę.

Czy moglibyście podpowiedzieć mi jak ogarnąć ten problem?

enum KEY {
  SECTIONS = 'sections'
}

export const useSections = () => {
  const { data, isLoading } = useQuery<SectionsType>(
    [KEY.SECTIONS],
    async () => axios.get(`/${KEY.SECTIONS}.json`).then((response) => response.data),
    {
      initialData: {} as SectionsType
    }
  );

  return { data, isLoading };
};

 

Odnośnik do komentarza
Udostępnij na innych stronach

28 minut temu, Carnage napisał:

Niestety, gdy ustawiam parametr initialData na pusty obiekt

Po co? Typescript nie lubi pustych obiektów. Nie bez powodu data jest undefined.

 

Odnośnik do komentarza
Udostępnij na innych stronach

Z tego względu, że podczas przesyłania propsów będących stringami pojawia mi się wartość undefined, która wywala mi błąd przy renderowaniu komponentu składającego się z nagłówka oraz opisu.

import { CircularProgress } from '@mui/material';
import { useEffect } from 'react';
import Welcome from '../components/Welcome';
import { useSections } from '../services';

const Home = (): JSX.Element => {
  const { data, isLoading } = useSections();

  useEffect(() => {
    if (data) {
      console.log(data);
    }
  }, [isLoading]);

  return (
    isLoading ? (
      <div className="main__loading">
        <CircularProgress />
      </div>
    )
      : (
        <>
          <Welcome />
          <div />
        </>
      )
  );
};

export default Home;

Dlatego zależało mi, aby zainicjować obiekt omijający ten problem

import Information from '../Information';

const Welcome = (): JSX.Element => (
  <Information
    headline="Find true power in your data with Ensome"
  >
    Sed ut perspiciatis unde omnis iste natus error
  </Information>
);

export default Welcome;

 

Odnośnik do komentarza
Udostępnij na innych stronach

3 minuty temu, Carnage napisał:

wywala mi błąd przy renderowaniu komponentu

jaki? Daj przykład kompletnego użycia zmiennej `data`. W przykładzie masz że ma Ci się pojawić w konsoli przy pierwszym wyrenderowaniu.

Odnośnik do komentarza
Udostępnij na innych stronach

1.png.3f023060d2555eafb1e92cd96a8fc3af.png

Odnośnik do komentarza
Udostępnij na innych stronach

Ledwo co widać na tym screenie.

Odnośnik do komentarza
Udostępnij na innych stronach

Przy czym headline i description chciałbym zachować jako required props, a nie wszystko dawać jako opcjonalne

@aXenDev Poprawiłem

import { CircularProgress } from '@mui/material';
import { useEffect } from 'react';
import Welcome from '../components/Welcome';
import { useSections } from '../services';

const Home = (): JSX.Element => {
  const { data, isLoading } = useSections();

  useEffect(() => {
    if (data) {
      console.log(data);
    }
  }, [isLoading]);

  return (
    isLoading ? (
      <div className="main__loading">
        <CircularProgress />
      </div>
    )
      : (
        <>
          <Welcome content={data?.welcome} />
          <div />
        </>
      )
  );
};

export default Home;

 

Odnośnik do komentarza
Udostępnij na innych stronach

Jakie typy są w `SectionsType`?

Odnośnik do komentarza
Udostępnij na innych stronach

@aXenDev  SectionProps zawiera tylko content, który jest obiektem składającym się z 2 stringów

export type SectionsType = {
  [key in 'welcome']: SectionType
};

export type SectionType = {
  headline: string;
  description: string;
};

export interface SectionProps {
  content?: SectionType;
}

 

Odnośnik do komentarza
Udostępnij na innych stronach

Zaraz, zaraz...

5 minut temu, Carnage napisał:
export type SectionsType = {
  [key in 'welcome']: SectionType
};

Po co to jest? API jest dynamiczne? Jak tak to API jest źle napisane a sens używania TypeScripta traci sens.

Odnośnik do komentarza
Udostępnij na innych stronach

Akurat utworzyłem Realtime database w Firebase i za pomocą axiosa pobieram dane - stąd taki dziwny typ, ale przed pull requestem chciałem to poprawić. Także backendu nie mam

Odnośnik do komentarza
Udostępnij na innych stronach

Teoretycznie to kiedy używasz query z react-query musisz mieć stan isLoading oraz isError, który od razu zwracasz w komponencie np.

import { CircularProgress } from '@mui/material';
import Welcome from '../components/Welcome';
import { useSections } from '../services';

export const Home = () => {
  const { data, isLoading, isError } = useSections();

  if (isLoading) {
    return (
      <div className="main__loading">
        <CircularProgress />
      </div>
    );
  }

  if (isError) return <div>Error!</div>;

  return <Welcome content={data} />;
};

Wtedy:

import Information from '../Information';

interface Props {
  data?: SectionsType;
}

export const Welcome = ({ data }: Props) => {
  console.log(data?.welcome);

  return (
    <Information headline="Find true power in your data with Ensome">
      Sed ut perspiciatis unde omnis iste natus error
    </Information>
  );
};

Z czego z takim typowaniem SectionsType zawsze będzie ryzyko że wartość welcome będzie mieć undefined.

Typowanie API powinno wyglądać tak:

interface Props {
  welcome: {
    headline: string;
    description: string;
  };
}

 

Odnośnik do komentarza
Udostępnij na innych stronach

Hmm... jeśli chodzi o isError, to za bardzo nie mam pojęcia, gdzie go wepchnąć. Zastanawiam się, czy nie dorzucić go do warunku z CircularProgress, choć nie wiem, czy nie będzie to zbyt mylne dla potencjalnego użytkownika.

Poza tym, jak można rozwiązać kwestię typowania, jeżeli sekcji będzie o wiele więcej? Z tego też powodu postawiłem na type z [key in...]

6 minut temu, aXenDev napisał:
interface Props {
  welcome: {
    headline: string;
    description: string;
  };
}

 

 

Odnośnik do komentarza
Udostępnij na innych stronach

8 minut temu, Carnage napisał:

Poza tym, jak można rozwiązać kwestię typowania, jeżeli sekcji będzie o wiele więcej? Z tego też powodu postawiłem na type z [key in...]

Tyle ile jest zaimplementowane w API tyle masz napisać, nigdy nie więcej! Jeżeli pojawią się nowe pola to musisz je napisać ręcznie. Takie uroki REST API ❤️

Jak zależy Ci na dokładnym typowaniu i co najważniejsze automatycznym użyj graphql z biblioteką graphql-codegen.

 

Przykład isError dałem Ci wyżej jak masz go umieścić.

Odnośnik do komentarza
Udostępnij na innych stronach

Wybacz, dopiero teraz zauważyłem przykład z isError 😅 Dziękuję za wszystkie podpowiedzi. Także jeszcze dzisiaj sprawdzę, czy wszystko będzie poprawnie śmigać 😉

Odnośnik do komentarza
Udostępnij na innych stronach

Wszystko poprawiłem i nie ma już żadnych błędów. Dodatkowo ustawiłem initialData zgodnie z Twoimi wskazówkami typowania. Także jeszcze raz dzięki wielkie za pomoc @aXenDev. Temat do zamknięcia 😉

Odnośnik do komentarza
Udostępnij na innych stronach

Gość
Ten temat został zamknięty. Brak możliwości dodania odpowiedzi.
  • Dodaj nową pozycję...
  • Dodaj nową pozycję...