# ასინქრონული სტეტის მენეჯმენტი

## პრობლემა

api-იდან წამოღებული ინფორმაციის მენეჯმენტი და წამოღებაც კი არის გასაკვირად ჩელენჯინგი რეაქტში.

შეგვიძლია უბრალოდ დავწეროთ ასეთი რამ როცა მოგვინდება რომ წამოვიღოთ ბექიდან ინფორმაცია და გამოვიყენოთ

```typescript
import { useEffect, useState } from 'react';
import { getOpportunities } from 'utils/apis/opportunities';

const Demo = () => {
  const [data, setData] = useState([]);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<any>(null);

  useEffect(() => {
    (async () => {
      try {
        setLoading(true);
        const response = await getOpportunities();
        const data = await response.json();
        setData(data);
      } catch (error: any) {
        setError(error);
      } finally {
        setLoading(false);
      }
    })();
  }, []);

  if (loading) {
    return <div>Loading...</div>;
  }

  if (error) {
    return <div>Error: {error.message}</div>;
  }

  return (
    <div>
      <h1>Opportunities</h1>
      <ul>
        {data.map((opportunity) => (
          <li key={opportunity.id}>{opportunity.title}</li>
        ))}
      </ul>
    </div>
  );
};

export default Demo;

```

მაგრამ აქ უამრავი პრობლემაა. ჯერ ერთი რომ useEffect-ს ვიყენებთ ინფორმაციის წამოიღებისთვის რაც არ არის კარგი იდეა (ამაზე დეტალებში სხვა სექციაში ვისაბრებთ), ყველა სტეიტის დაჰენდვლა, ლოადინგის data-ის, ერრორის ჩვენით გვიწევს ყველა ჯერზე, ინფორმაციის ახლიდან წამოღება რომ დაგვჭირდეს მაშინ რას ვიზამთ? ანუ რომ მოგვინდეს ოპპორტუნიტების ახლიდან წამოღება როცა ახალი დაემატება, useEffect-ში ჩავამატებთ დეპენდენსის რომელსაც შევცვლით, ესეც არასწორი გამოყენება useEffect-ის, ან შეგვიძლია რომ ახლიდან დავწეროთ წამოღების ლოგიკა და ეგ ეგრე შევცვალოთ, სადაც ისევ მოგვიწევს ჩვენ ლოადინგის და ერრორის ახლიდან დაჰენდვლა.&#x20;

ეს დიდ აპლიკაციაებში ძალიან მალე გაიქცევა ხელიდან და ძალიან ძნელი დასამენეჯებელი იქნება.

მენეჯმენტის გარდა მერე ქეშირება დაგვჭრირდება, retry policy, pooling, infinite scroll, პოსტ რექუესტების გაგზავნაც დაგვჭირდება, ყველა კომპონენტიდან ახლიდან რომ არ წავიდეთ ბექში ეგ დაგვჭირდება.

ეს ყველაფერი ხელით გაკეთებადია რათქმაუნდა მაგრამ საკმაოდ ბევრი საქმეა და ხელიდან იმპლიემნტაცია ამის დიდად არ ღირს.

## პრობლემის მოგვარება (ვერსია 1)

უადველსი ვერსია რომ ეს მოვაგვაროთ იქნება ერთი custom hook-ს გაკეთება, სადაც არ გამოვიყენებთ useEffect-ს, რაღაცა ამდაგვარი

```typescript
import { AxiosResponse } from 'axios';
import { useState } from 'react';

export const useFetch = <T extends AxiosResponse, K = T['data']>(
  handler: () => Promise<T>,
  transformData: (arg0: T) => K,
) => {
  const [data, setData] = useState<K | null>(null);
  const [loading, setLoading] = useState<boolean>(true);
  const [error, setError] = useState<any>(null);

  if (!loading) {
    () =>
      (async () => {
        try {
          setData(transformData(await handler()));
        } catch (error) {
          setError(error);
        } finally {
          setLoading(false);
        }
      })();
  }

  const alterData = (data: K) => {
    setData(data);
  };

  return { data, loading, error, alterData };
};

```

ეს საკმაოდ ადვილი ჰუკია მაგრამ ამის პრობლემა ის არის რომ ბევრი რაღაცა არ შეიძლება და მერე ყვეალფრის იმპლიმნეტაცია ხელით მოგივწევს, მაგრამ თU პატარა აპლიკაცია და ბევრი რექუესტის გაგზავნა არ დაგვჭირდება ამის გამოყნეება სრულიად ვალიდურია.

{% tabs %}
{% tab title="კარგი" %}
* მთელი კოდი ჩვენი აპლიკაციის მხარეს არის და დეპენდენსები არ გვაქ
* ყველა რექუესტის მოთხოვნა ერთი ადგილიდან იქნება რამე მოდიფიკაცია თუ დაგვჭირდება გლობალურად, მაგ: ქეშირება, საკმაოდ ადვილი ჩასამატებელი იქნება
* არ ვიყენებთ useEffect-ს
{% endtab %}

{% tab title="ცუდი" %}
* გლობალური კონტექსტის, ქეშირების, განახსლების, pooling, inifnite scroll და სხვა ბევრი რაღაცის ჩამატება ჩვენით მოგვიწევს რაც აპლიკაციის კომპლექსიურობას საკმაოდ გაზრდის.
* პოსტ რექუესტების გაგზავნა ასე საკმაოდ არა კომფორტული იქნება და ვერც გამოვიყენებთ ამაში
{% endtab %}
{% endtabs %}

## პრობლემის მოგვარება (ვერსია 2)

ალბათ საუკეთესო გზა რომ მოვაგვაროთ ასინქრონული სტეტის მენეჯმენტი არის [tanstack query](https://tanstack.com/query/latest/docs/framework/react/overview), tanstack ქუერი ბევრად კომპლექსური და დიდია ვიდრე უბრალოდ useFetch მაგრამ რათქმუნდა ბევრად უკეთესი და რეკომენდირებული გზა არის რომ ასინქრნული სტეტები დავამენეჯოთ.

tanstack გვთავაზობს საკმაოდ ბევრ რამ, რამოდენიმე tan stack query-ს ფიჩერები რომ ჩამოვთვალოთ: ქეშირება, ქეშირიებს ადვილი ინვალიდაცია და კონტროლი, გლობალური ლოადინგი, კომპონენტებს და გვერდებს შორის ინფორმაციის გაზიარება ახლიდან ბექში გაგზავნის გარეშე, background fetching, ლოადინგის და ერორის სტეიტი,  post request-ების ადვილად დაჰენდვლა, გასაოცარი devtooling და სხვა ბევრი რამ, აუცულებლად გირჩევთ დოკუმენტაციას გადახედოთ იმისთვის რომ ყველაფერი იცოდეთ აქ მე არ და ვერ დავფარავ ბევრ რამეს.

### რა არის tan stack query

როგორც ზემოთ ვახსენე tanstack არის ასინქრნული სტეტის მენეჯმენტის საშულება, ჩვენ როცა გვსურს რაიმე რექუესტი გაგავზავნოთ ბექში და წამოვიღეოთ ბლოგების სია ჩვენ დავწერდით ასეთ რაღაცას.

```typescript
const { data, isLoading, isError } = useQuery({
  queryFn: () => axios.get('api/blogs'),
});

console.log({ data, isLoading, isError });
```

ამის დაწერის მერე როცა ეს კომპონენტი დარენდერდებოდა მაშინვე გაიგზავნებოდა ბლოგების api-ზე მოთხოვნა, useQuery უკან არა მარტო is loading, is Error და data-ს აბრუნებს ამის ზემოთ კიდე ბევრი ინფორმაცია აქვს რაც შეგიძლიათ [დოკუმენტაციაში](https://tanstack.com/query/latest/docs/framework/react/reference/useQuery) იხილოთ.

ეს კი კარგია მარა  მარტო ეს რომ შეეძლოს ასე ქებას არ დავიწყებდი, ეხლა დავუშვათ მოგვინდა ამ ბლოგების გამოყენება სხვა კომპონენტში, რა შეგვიძლია რომ ვქნათ?&#x20;

* შეგვიძლია რომ ეს data პროპად ჩავატანოდ
* შეგვიძლია იმ კომპონენტში ახლიდან გამოვიძახოთ ეს api და ახლიდან წავიდეთ ბექში (bad idea)
* შეგვიძლია კონტექსტი შევქმნათ და მანდ ჩავდოთ ეს data და მერე სხვგან გამოვიყენოთ როცა გვინდა.

ესენი კი შეგვიძლია რომ ვქნათ მაგრამ რათქმაუნდა ეს ქეისი მოგვარებული აქვს tan stack-ს query key-ების საშულებით, ჩვენ შეგვიძLია რომ გადავწეროთ ზემოთ დაწერელი კოდი შემდეგნაირად

```typescript
const { data, isLoading, isError } = useQuery({
   queryFn: () => axios.get('api/blogs'),
   queryKeys: ["BLOGS"]
})
```

კაი და ამის დაწერა რას გვაძლევს?&#x20;

შემდეგში რომცა ჩვენ გამოვიძახებთ useQuery-ის და გადავაწვდით queryKeys-ში იგივე მასივს ჩვენ ნებისმიერ კომპონენტში ამოვიღებთ იგივე  ინფორმაციას ბექენდში წასვლის გარეშე! და როცა ერთ ადგილზე განვაახლებთ რათქმაუნდა ასევე ყველგან განახდლდება! ერთერთი საუკეთესო ნაწილი tanstack-ის გამოყნების ეს არის, ბევრად მარტივი ხდება ინფორმაციის გაზიარება კომპონენტებსა და გვერდებს შორის, მეტი ინფორმაცია იხილეთ [დოკუმენტაცაში](https://tanstack.com/query/latest/docs/framework/react/guides/query-keys) .

სხვა კიდე ბევრი კარგი რამ აქვს tan stack-ს მაგრამ ყველაფერი რომ ჩამოვთვალო აქ მთელი დღე ვიქნებით ასერომ უბრალოდ იხილეთ [დოკუმენტცია](https://tanstack.com/query/latest/docs/framework/react/guides/important-defaults)

### როდის ჯობია tan stack query?

თუ ჩვენ გვაქ რამდენიმე გვერდი, მოგვიწევს ხოლმე ინფორმაციის ხშირად განახლება, ბევრი query პარამეტრები გვექნება, თუ ინფროამციის გაზზიარება გვჭირდება გვერდებს და კომპონენტებს შორის, თუ გვჭირდება  ქეშირება, ქეშის ადვილი ინვალიდაცია, გასაოცარი დევტულინგი, ჯობია გამოიყენო tanstack query, თითქმის ყველა ქეისში თუ კომპლექსური აპლიკაციიაა და 2 ციფრში ითვლება თქვენი api request-ების რამოდენობა ჯობია tan stack გამოიყენოთ თუ რამე ტექნიკური ლიმიტიაცია არ არის თქვენთვის.&#x20;

{% tabs %}
{% tab title="Pros" %}
* ქეშირება
* ქეშის ინვალიდაცია
* გლობალური კონტექსტი ინფომრაციისითვის
* კარგი დევტულინგი
* battle tested (საკმაოდ დიდი ხანია არსებობს ეს ლაიბრარი და ახალი სათამაშო არ არის)
* სისწრაფე მიღებული useEffect-ის არ გამოიყენბით
* clean api


{% endtab %}

{% tab title="Cons" %}
* learning curve, რაც არ უნდა ითქვას მაინც ლიაბრარია და სწავლა მოგიწევთ ცალკე, თავისი პრობლმები აქვს მაგრამ საკმაოდ ადვილი დასაწყებია და მაინც ღირს ჩემი აზრით
* nextjs/nuxtjs-ს თან ცოტა პრობლემატური არის დასეთაპება სწორად.
* აპლიკაცაში საკმაოდ გეცვლება ინფრასტრუქტურა api რექუესტების გაგაგზავნაზე, რაც შეიძლება არაკომფორტული იყოს დასაწყისში.
{% endtab %}
{% endtabs %}

{% content-ref url="asinkronuli-stetis-menejmenti/tan-stack-query-is-gamoqienebis-tsesebi" %}
[tan-stack-query-is-gamoqienebis-tsesebi](asinkronuli-stetis-menejmenti/tan-stack-query-is-gamoqienebis-tsesebi)
{% endcontent-ref %}

