32-წუთიანი სამუშაო სესია კითხვაზე, რომელიც ჩუმად წყვეტს თქვენი აპლიკაციის არქიტექტურას: სად ცხოვრობს მდგომარეობის თითოეული ნაწილი? React-ის ჩაშენებული საშუალებებიდან გლობალურ სთორებამდე და სერვერის მდგომარეობის ქეშებამდე — და პატიოსანი კომპრომისები მათ შორის.
სანამ რომელიმე ბიბლიოთეკას მიმართავთ, თითოეულ მნიშვნელობას ერთი კითხვა დაუსვით: თქვენ ფლობთ მას, თუ ეს სერვერზე მცხოვრები რაღაცის ასლია? მდგომარეობის მართვის თითქმის ყველა შეცდომა ამ ორის აღრევიდან იბადება — და „Redux გვჭირდება“ ტიპის საუბრების უმეტესობა ქრება, როგორც კი მათ გამიჯნავთ.
ერთი და იგივე სიტყვა, ორი სხვადასხვა პრობლემა. კლიენტის მდგომარეობა თქვენია და მყისიერი; სერვერის მდგომარეობა ნასესხები ასლია, რომელიც ახალი უნდა შეინარჩუნოთ.
თითქმის ყველაფერი აქ ერთ გაკვეთილზე დადის: შეწყვიტეთ ქეშის ხელით აწყობა useState + useEffect-ისგან და შეწყვიტეთ თქვენივე UI-ის მდგომარეობის სერვერზე განთავსება.
აპლიკაციების უმეტესობას გაცილებით ნაკლები გლობალური მდგომარეობა სჭირდება, ვიდრე ჰგონია. ბიბლიოთეკას მაშინ მიმართეთ, როცა ამ სამს ნამდვილად აღარ ეყოფა ადგილი. თავად ჰუკების მექანიკისთვის იხილეთ Modern React — აქ ყურადღებას ვამახვილებთ იმაზე, თითოეული სად ჯდება.
ნაგულისხმევი არჩევანი. მდგომარეობა, რომელსაც ერთი კომპონენტი ფლობს (და შესაძლოა ერთი-ორი დონით ქვემოთ გადასცემს). როცა ორი განახლება წინა მნიშვნელობაზეა დამოკიდებული, ფუნქციური ფორმა გამოიყენეთ.
როცა რამდენიმე ქმედება დაკავშირებულ მდგომარეობას სტრუქტურირებულად ცვლის, რედიუსერი ლოგიკას ერთ ტესტირებად ფუნქციაში კრებს, ხუთი მიმოფანტული setState გამოძახების ნაცვლად.
Context არ არის მდგომარეობის მენეჯერი — ის ტრანსპორტია. ის მნიშვნელობას ხეში ქვემოთ ატარებს ისე, რომ props ყოველ შრეზე არ გაატაროთ. ის არაფერს ქეშირებს და შერჩევით განახლებებს არ აკეთებს.
context-ის მნიშვნელობის ნებისმიერი ცვლილება ხელახლა არენდერებს ყველა consumer-ს — მათაც კი, ვინც მხოლოდ არარელევანტურ ველს კითხულობს. Context-ს ჩაშენებული სელექტორები არ აქვს.
ორი რამ აკბენინებს Context-ს. პირველი — სწრაფად ცვალებადი მნიშვნელობის (მაუსის პოზიცია, მზარდი სია) ერთ კონტექსტში მოთავსება ნელა ცვალებადებთან ერთად. მეორე — მნიშვნელობად ყოველ რენდერზე ახალი ობიექტის გადაცემა: ახალი იდენტობა ყოველთვის ცვლილებად ითვლება.
გლობალური სთორები ორ პრობლემას წყვეტს, რომელსაც Context ვერ ახერხებს: ისინი კომპონენტების ხის გარეთ ცხოვრობენ და კომპონენტები ერთ ნაჭერს ეწერებიან — ამიტომ ცვლილება ხელახლა მხოლოდ იმ კომპონენტებს არენდერებს, რომლებიც ამ ნაჭერს კითხულობენ. სწორედ ეს სელექტორული მოდელია მათი გამოყენების ნამდვილი მიზეზი.
დაამატეთ ელემენტი და ხელახლა მხოლოდ Count რენდერდება — Avatar და Header სხვა ნაჭრებს კითხულობენ და უქმად რჩებიან.
ოთხივე გაზიარების პრობლემას წყვეტს. ისინი სააზროვნო მოდელითა და ცერემონიის რაოდენობით განსხვავდებიან. თითო ხაზი დადებითზე, უარყოფითზე და იმაზე, როდის ჯდება თითოეული.
ერთი create გამოძახება ჰუკს აბრუნებს; არც პროვაიდერი, არც ბოილერპლეიტი. სელექტორები ჩაშენებულია. პრაგმატული ნაგულისხმევი არჩევანი აპლიკაციების უმეტესობისთვის 2026 წელს.
ოფიციალური, თანამედროვე Redux. სლაისები ქმედებებსა და რედიუსერებს თქვენს ნაცვლად ქმნიან; ძლიერი კონვენციები, დროში მოგზაურობის DevTools და მიდლვეარების ეკოსისტემა.
მდგომარეობა პატარა atom პრიმიტივებისგან იგება, რომლებიც ერთმანეთს ერწყმის; გამოთვლილი ატომები მხოლოდ მაშინ გადაითვლიან, როცა მათი შემავალი მონაცემები იცვლება. გრანულარული თავისი ბუნებით, React-ისთვის ბუნებრივი შეგრძნებით.
სიგნალი არის მნიშვნელობა, რომელიც პირდაპირ ატყობინებს თავის მკითხველებს და კომპონენტის დონის შედარებას გვერდს უვლის. მშობლიურია SolidJS-სა და Angular-ში; React-ში — Preact Signals-ის მეშვეობით. გრანულარული განახლებების მომავალი მიმართულება.
პატიოსანი ნაგულისხმევი: თუ Context პლუს მდგომარეობის ცოტა აწევა ჯერ კიდევ მუშაობს, არცერთი მათგანი არ გჭირდებათ. როცა დაგჭირდებათ, Zustand ყველაზე პატარა ნაბიჯია წინ გუნდების უმეტესობისთვის.
წამოღებისთანავე ხელში გიჭირავთ ასლი, რომელიც შეიძლება არასწორი იყოს. სერვერის მდგომარეობის ბიბლიოთეკა ამ ასლს პატიოსანს ხდის: ის ერთნაირ მოთხოვნებს აერთიანებს, გასაღებით ქეშირებს, მყისიერად აბრუნებს ნაქეშირებულს და ფონურად ახლებს, და ინვალიდაციის ნათელ გზას გაძლევთ. იხილეთ ასევე Caching & CDNs ქეშირების საფუძვლებისთვის და API Design იმ ენდპოინტებისთვის, რომლებიც ამ გასაღებების უკან დგას.
ქეში მაშინვე პასუხობს (დაძველებულით), ფონურად ხელახლა წამოიღებს და შემდეგ ახალი მონაცემებით ხელახლა რენდერდება. შეკითხვის გასაღები თითოეული ქეშის ჩანაწერის იდენტობაა.
ეს ქეშებია და არა სთორები. აირჩიეთ იმის მიხედვით, რამდენი გჭირდებათ და რას იყენებთ უკვე.
ქეშირება, მოთხოვნების გაერთიანება, ფონური ხელახალი წამოღება, ხელახალი მცდელობები, პაგინაცია, ოპტიმისტური განახლებები და პირველხარისხოვანი DevTools. ბმულები React-ის, Vue-ს, Svelte-ს, Solid-ისა და სხვა ფრეიმვორკებისთვის.
staleTime, ქეშის სიცოცხლის ხანგრძლივობა.Vercel-ისგან, დასახელებული stale-while-revalidate-ის მიხედვით. პატარაuseSWR(key, fetcher) ფარავს წამოღებას, ქეშირებასა და ხელახალ ვალიდაციას ძალიან მცირე API-თ.
Redux Toolkit-ის ნაწილი. თქვენ აღწერთ ენდპოინტებს; ის ჰუკებს გენერირებს და ქეშს თქვენს Redux სთორში ინახავს, თეგებზე დაფუძნებული ინვალიდაციითა და თქვენი API-ს სქემიდან კოდის სურვილისამებრ გენერაციით.
როგორ ავირჩიოთ: უკვე RTK-ზე ხართ → RTK Query. მსუბუქი, ძირითადად წაკითხვები → SWR. რაიმე უფრო მდიდარი → TanStack Query. სამივე სჯობს ხელით აწყობილ useEffect წამოღებას.
ყოველი მნიშვნელობა, რომელსაც ინახავთ, შეიძლება სინქრონიდან გავიდეს. ორი ჩვევა ბაგების უმეტესობას აღკვეთს: გამოთვალეთ ყველაფერი, რისი გამოთვლაც არსებული მდგომარეობიდან შეგიძლიათ, და თითოეული ერთეულისთვის ერთი ჭეშმარიტების წყარო შეინარჩუნეთ, ასლების მიმოფანტვის ნაცვლად.
const [items, setItems] = useState([]) const [total, setTotal] = useState(0) // duplicated truth function add(it) { setItems([...items, it]) setTotal(total + it.price) // forget this once → out of sync }
const [items, setItems] = useState([]) const total = items.reduce((s, it) => s + it.price, 0) // expensive? memoize — still derived, just cached const total = useMemo( () => heavySum(items), [items], )
შეინახეთ items; დანარჩენი ყველაფერი მისი ფუნქციაა. useMemo-ს მხოლოდ მაშინ მიმართეთ, როცა გამოთვლა ნამდვილად ძვირია — ჯერ სისწორე, მერე წარმადობა.
როცა ერთი და იგივე ერთეული ბევრ ადგილას ჩნდება, მისი ასლები ნუ ჩააშენებთ. შეინახეთ თითოეული ერთეული ერთხელ, id-ის მიხედვით, და მიუთითეთ მასზე. განაახლებთ ერთ ჩანაწერს და ყველა ხედი განახლდება — დასაწევი დაძველებული დუბლიკატები არ რჩება. ასე ფიქრობს მონაცემთა ბაზა და ამიტომაც აქვს Redux-ს ერთეულების ადაპტერი.
გადაარქვით Ada-ს სახელი ერთხელ users[9]-ში და ორივე პოსტი აისახავს — დასავიწყებელი დუბლიკატი არ არსებობს.
ერთი შენახული მასივი; ჯამი, რაოდენობა და გაფილტრული ხედები რენდერზე გამოითვლება — სინქრონში შესანარჩუნებელი არაფერია.
useState-ს ჰკითხეთ: ხომ არ შემიძლია ამის ნაცვლად გამოთვლა? თუ კი, ნუ შეინახავთ.სანამ ფილტრებისთვის ან ვიზარდისთვის სთორს დაამატებთ, შეამოწმეთ, ხომ არ ეკუთვნის ეს მდგომარეობა URL-ს ან ხომ არ რჩება ფორმის შიგნით. ორივე მდგომარეობის ნამდვილი კონტეინერია, რომელიც უკვე გაქვთ — და მათი გამოყენება ბაგების მთელ კატეგორიებს შლის.
ჩადეთ ფილტრები და პაგინაცია შეკითხვის სტრიქონში და ბმული არის მდგომარეობა — სთორი აღარ სჭირდება და ყოველი ხედი გასაზიარებელია.
ფორმის დრაფტი დროებითი, ლოკალური კლიენტის მდგომარეობაა — გლობალურ სთორს იშვიათად ეკუთვნის. ნამდვილი არჩევანია კონტროლირებადი (React ფლობს ყოველ კლავიშს) vs არაკონტროლირებადი (მნიშვნელობას DOM ფლობს, React კი გაგზავნისას კითხულობს). არაკონტროლირებადი ფორმები გაცილებით ნაკლებად რენდერდება — სწორედ ამიტომ იხრებიან ფორმების ბიბლიოთეკები ამ მხარეს.
დრაფტს ფორმის ბიბლიოთეკა ფლობს. სთორამდე ან სერვერამდე ის მხოლოდ მაშინ აღწევს, როცა მომხმარებელი გაგზავნას დააჭერს.
არ არსებობს ერთი „მდგომარეობის მართვის ბიბლიოთეკა“ — არსებობს კატეგორიები და აპლიკაციების უმეტესობა რამდენიმეს ერთად იყენებს. მიმართეთ მდგომარეობის თითოეული ნაწილი მფლობელობის მიხედვით და არჩევანი თითქმის თავად კეთდება.
სერვერი, URL და ერთი ქვეხე მდგომარეობის უმეტესობას შთანთქავს. გლობალური კლიენტის სთორი უკანასკნელი გამოსავალია და არა პირველი.
useState/useReducer, ასწიეთ მხოლოდ იმდენად, რამდენადაც საჭიროა.Redux Toolkit კვლავ შესანიშნავია დიდი გუნდებისთვის, რომლებსაც დაწესებული სტრუქტურა და აუდიტისთვის მოსახერხებელი ლოგიკა სურთ. მაგრამ ისტორიულად Redux-ის დიდი ნაწილი სინამდვილეში სერვერის მდგომარეობა იყო — და ეს საქმე ახლა შეკითხვების ქეშს ეკუთვნის. ჯერ ეს ორი გამიჯნეთ; ბევრი აპლიკაცია აღმოაჩენს, რომ გლობალური კლიენტის მდგომარეობა თითქმის არ სჭირდება.
useState + useEffect.useState → აწევა → Context → სთორი სელექტორებით — მხოლოდ იმდენად, რამდენადაც საჭიროება ჩნდება.ხუთი სწრაფი კითხვა კლიენტი/სერვერის გაყოფაზე, Context-ზე, სთორებზე, ქეშირებასა და იმაზე, სად ეკუთვნის მდგომარეობა — მყისიერი უკუკავშირი, ავტორიზაციის გარეშე.
ნავიგაცია ← → ღილაკებით ან სქროლით · უკან ბიბლიოთეკაში