{"id":30596,"date":"2023-04-13T13:18:27","date_gmt":"2023-04-13T11:18:27","guid":{"rendered":"https:\/\/nearshore-it.eu\/artykuly\/jesli-nie-redux-to-co-zarzadzanie-stanem-aplikacji-w-react\/"},"modified":"2024-09-30T06:46:36","modified_gmt":"2024-09-30T04:46:36","slug":"jesli-nie-redux-to-co-zarzadzanie-stanem-aplikacji-w-react","status":"publish","type":"post","link":"https:\/\/nearshore-it.eu\/pl\/artykuly\/jesli-nie-redux-to-co-zarzadzanie-stanem-aplikacji-w-react\/","title":{"rendered":"Je\u015bli nie\u00a0Redux, to\u00a0co?\u00a0Zarz\u0105dzanie stanem aplikacji w\u00a0React"},"content":{"rendered":"\n<div class=\"table-of-contents\">\n    <p class=\"title\">Spis tre\u015bci:<\/p>\n    <ol>\n                    <li><a href=\"#Zarz\u0105dzanie-stanem-w-React\">1.  Zarz\u0105dzanie stanem w React<\/a><\/li>\n                    <li><a href=\"#Czym-jest-Redux-i-jak-dzia\u0142a?\">2.  Czym jest Redux i jak dzia\u0142a?<\/a><\/li>\n                    <li><a href=\"#Wykorzystanie-innych-rozwi\u0105za\u0144\">3.  Wykorzystanie innych rozwi\u0105za\u0144<\/a><\/li>\n                    <li><a href=\"#Kt\u00f3re-rozwi\u0105zanie-wybra\u0107?\">4.  Kt\u00f3re rozwi\u0105zanie wybra\u0107?<\/a><\/li>\n                    <li><a href=\"#Zarz\u0105dzanie-stanem-aplikacji-\u2013-podsumowanie\">5.  Zarz\u0105dzanie stanem aplikacji \u2013 podsumowanie<\/a><\/li>\n            <\/ol>\n<\/div>\n\n\n<h2 class=\"wp-block-heading\" id=\"Zarz\u0105dzanie-stanem-w-React\">Zarz\u0105dzanie stanem w React<\/h2>\n\n\n\n<p>Kto\u015b stworzy\u0142 aplikacj\u0119 z przyciskiem. Wciskasz go i za ka\u017cdym razem wy\u015bwietla si\u0119 inna warto\u015b\u0107. Pewnie zastanawiasz si\u0119, co dzieje si\u0119 <strong>\u201epod spodem\u201d.<\/strong> To albo czary, albo\u2026 zarz\u0105dzanie stanem aplikacji. Tym razem zajmiemy si\u0119 tym drugim tematem. Zarz\u0105dzanie stanem w <a href=\"https:\/\/nearshore-it.eu\/pl\/artykuly\/najlepsze-frameworki-frontendowe\/\" target=\"_blank\" data-type=\"URL\" rel=\"noreferrer noopener\">React <\/a>to <strong>proces kontrolowania i aktualizowania danych w aplikacji.<\/strong> <\/p>\n\n\n\n\n\n<div style=\"height:30px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img decoding=\"async\" src=\"https:\/\/nearshore-it.eu\/wp-content\/uploads\/2024\/09\/Redux-Gif.gif\" alt=\"Redux\" class=\"wp-image-6620\" title=\"\"><\/figure>\n<\/div>\n\n\n<div style=\"height:30px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>Jest jednym z kluczowych zagadnie\u0144 przy pracy z bibliotek\u0105 programowania JavaScript.  Stan to taka warto\u015b\u0107, kt\u00f3ra zmienia si\u0119 na przyk\u0142ad na skutek interakcji u\u017cytkownika z aplikacj\u0105. W React stan zazwyczaj przechowywany jest w komponentach, a jego zmiana mo\u017ce powodowa\u0107 ponowne renderowanie komponentu lub ca\u0142ego drzewa komponent\u00f3w. Zarz\u0105dzanie stanem jest dosy\u0107 istotne. Pozwala nam tworzy\u0107 dynamiczne i interaktywne aplikacje \u2013 dzi\u0119ki temu aplikacja mo\u017ce:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>dostosowywa\u0107 si\u0119 do zmieniaj\u0105cego si\u0119 stanu,<\/li>\n\n\n\n<li>reagowa\u0107 na interakcj\u0119 u\u017cytkownika,<\/li>\n\n\n\n<li>wykonywa\u0107 pewne akcje w odpowiednich momentach.<\/li>\n<\/ul>\n\n\n\n<p>Jest to wa\u017cne w przypadku z\u0142o\u017conych aplikacji, w kt\u00f3rych wiele komponent\u00f3w zale\u017cy od stan\u00f3w w innych komponentach.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"Czym-jest-Redux-i-jak-dzia\u0142a?\">Czym jest Redux i jak dzia\u0142a?<\/h2>\n\n\n\n<p>Zapewne wi\u0119kszo\u015b\u0107 os\u00f3b zaznajomionych z React, s\u0142ysz\u0105c o zarz\u0105dzaniu stanem, przed oczami ma tylko jedno \u2013 Redux.<\/p>\n\n\n\n<p>Redux jest bibliotek\u0105 s\u0142u\u017c\u0105c\u0105 do zarz\u0105dzania stanem aplikacji w React. Jest to narz\u0119dzie, kt\u00f3re umo\u017cliwia tworzenie bardziej przewidywalnych i \u0142atwiejszych<strong> do testowania aplikacji poprzez uproszczenie zarz\u0105dzania stanem i zachowywania go w jednym miejscu<\/strong>. Redux wprowadza wiele poj\u0119\u0107, kt\u00f3re pozwalaj\u0105 na bardziej efektywne i przewidywalne zarz\u0105dzanie stanem. Jednym z nich jest jednostronny przep\u0142yw danych. Stan aplikacji jest przechowywany w jednym centralnym magazynie, tzw. store. Dane mi\u0119dzy store a komponentami przep\u0142ywaj\u0105 w odpowiedni spos\u00f3b, zgodny z architektur\u0105 Flux. Zmiany w stanie s\u0105 dokonywane tylko za pomoc\u0105 akcji, czyli prostych obiekt\u00f3w, kt\u00f3re opisuj\u0105 zmiany, jakie maj\u0105 by\u0107 wykonane w stanie aplikacji.<\/p>\n\n\n\n<p>Warto r\u00f3wnie\u017c wspomnie\u0107, \u017ce <strong>Redux mo\u017ce dzia\u0142a\u0107 niezale\u017cnie od Reacta<\/strong>. Biblioteka ta jest uniwersalna i mo\u017ce by\u0107 u\u017cywana w innych aplikacjach internetowych. Je\u015bli kto\u015b jednak poszukuje nieskomplikowanego, intuicyjnego narz\u0119dzia, to warto pozna\u0107 te\u017c inne dost\u0119pne opcje.<\/p>\n\n\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">import React from \"react\";\nimport { Provider, useDispatch, useSelector } from \"react-redux\";\nimport { createStore } from \"redux\";\n\n\nconst incrementAction = () => ({ type: \"INCREMENT\" });\nconst decrementAction = () => ({ type: \"DECREMENT\" });\n\n\nconst counterReducer = (state = 0, action) => {\n switch (action.type) {\n   case \"INCREMENT\":\n     return state + 1;\n   case \"DECREMENT\":\n     return state - 1;\n   default:\n     return state;\n }\n};\n\n\nconst store = createStore(counterReducer);\n\n\nconst Counter = () => {\n const count = useSelector((state) => state);\n const dispatch = useDispatch();\n\n\n return (\n   &lt;div>\n     &lt;div>Count: {count}&lt;\/div>\n     &lt;button onClick={() => dispatch(incrementAction())}>+&lt;\/button>\n     &lt;button onClick={() => dispatch(decrementAction())}>-&lt;\/button>\n   &lt;\/div>\n );\n};\n\n\nconst CounterApp = () => {\n return (\n   &lt;Provider store={store}>\n     &lt;Counter \/>\n   &lt;\/Provider>\n );\n};\n<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"Wykorzystanie-innych-rozwi\u0105za\u0144\">Wykorzystanie innych rozwi\u0105za\u0144<\/h2>\n\n\n\n<p>Na szcz\u0119\u015bcie istniej\u0105 r\u00f3\u017cne sposoby zarz\u0105dzania stanem aplikacji w React:<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Context API<\/strong><\/h3>\n\n\n\n<p>To wbudowane w React narz\u0119dzie do przekazywania danych mi\u0119dzy komponentami bez konieczno\u015bci przekazywania ich przez <strong>\u201epropsy\u201d<\/strong> (<em>w\u0142a\u015bciwo\u015bci, ang. properties<\/em>). Dzi\u0119ki temu mo\u017cna przekazywa\u0107 dane do komponent\u00f3w znajduj\u0105cych si\u0119 ni\u017cej w hierarchii bezpo\u015brednio z g\u00f3ry. Mo\u017cna to wykorzysta\u0107 do zarz\u0105dzania stanem aplikacji, przekazuj\u0105c stan do ca\u0142ej aplikacji lub tylko do cz\u0119\u015bci komponent\u00f3w.<\/p>\n\n\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">import React, { createContext, useContext, useState } from \"react\";\n\n\nconst CounterContext = createContext();\n\n\nconst CounterProvider = ({ children }) => {\n const [counter, setCounter] = useState(0);\n\n\n const increment = () => {\n   setCounter((prevCounter) => prevCounter + 1);\n };\n\n\n const decrement = () => {\n   setCounter((prevCounter) => prevCounter - 1);\n };\n\n\n return (\n   &lt;CounterContext.Provider value={{ counter, increment, decrement }}>\n     {children}\n   &lt;\/CounterContext.Provider>\n );\n};\n\n\nconst CounterDisplay = () => {\n const { counter } = useContext(CounterContext);\n\n\n return &lt;div>Counter: {counter}&lt;\/div>;\n};\n\n\nconst CounterButtons = () => {\n const { increment, decrement } = useContext(CounterContext);\n\n\n return (\n   &lt;div>\n     &lt;button onClick={increment}>+&lt;\/button>\n     &lt;button onClick={decrement}>-&lt;\/button>\n   &lt;\/div>\n );\n};\n\n\nconst CounterApp = () => {\n return (\n   &lt;CounterProvider>\n     &lt;CounterDisplay \/>\n     &lt;CounterButtons \/>\n   &lt;\/CounterProvider>\n );\n};<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>MobX<\/strong><\/h3>\n\n\n\n<p>To biblioteka, kt\u00f3ra umo\u017cliwia \u0142atwe zarz\u0105dzanie stanem aplikacji w React. W przeciwie\u0144stwie do Redux \u2013 MobX jest bardziej elastyczny i wymaga mniej kodu. U\u017cywa si\u0119 go do przechowywania stanu w obiektach, kt\u00f3re reprezentuj\u0105 dane aplikacji. MobX automatycznie aktualizuje widok, gdy dane zmieni\u0105 si\u0119 w magazynie.<\/p>\n\n\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">import React from \"react\";\nimport { observable } from \"mobx\";\nimport { observer } from \"mobx-react\";\n\nconst counterStore = observable({\n counter: 0,\n increment() {\n   this.counter++;\n },\n decrement() {\n   this.counter--;\n },\n});\n\nconst CounterDisplay = observer(() => &lt;div>Counter: {counterStore.counter}&lt;\/div>);\n\nconst CounterButtons = observer(() => (\n &lt;div>\n   &lt;button onClick={() => counterStore.increment()}>+&lt;\/button>\n   &lt;button onClick={() => counterStore.decrement()}>-&lt;\/button>\n &lt;\/div>\n));\n\nconst CounterApp = () => {\n return (\n   &lt;div>\n     &lt;CounterDisplay \/>\n     &lt;CounterButtons \/>\n   &lt;\/div>\n );\n};<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>RxJS<\/strong><\/h3>\n\n\n\n<p>To <a href=\"https:\/\/nearshore-it.eu\/pl\/artykuly\/programowanie-reaktywne-w-js-z-rxjs\/\" target=\"_blank\" data-type=\"URL\" rel=\"noreferrer noopener\">biblioteka reaktywna<\/a> do zarz\u0105dzania asynchronicznymi strumieniami danych. Mo\u017cna jej u\u017cywa\u0107 do zarz\u0105dzania stanem w aplikacji. RxJS pozwala na \u0142atwe reagowanie na zmiany w danych i wykonywanie akcji na podstawie tych zmian.<\/p>\n\n\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">import React, { useState, useEffect } from \"react\";\nimport { Subject } from \"rxjs\";\nimport { scan } from \"rxjs\/operators\";\n\nconst counterSubject = new Subject();\n\nconst counter$ = counterSubject.pipe(\n scan((count, operation) => {\n   if (operation === \"+\") {\n     return count + 1;\n   } else if (operation === \"-\") {\n     return count - 1;\n   } else {\n     return count;\n   }\n }, 0)\n);\n\nconst CounterDisplay = () => {\n const [counter, setCounter] = useState(0);\n\n\n useEffect(() => {\n   const subscription = counter$.subscribe(setCounter);\n   return () => subscription.unsubscribe();\n }, []);\n\n\n return &lt;h1>Counter: {counter}&lt;\/h1>;\n};\n\n\nconst CounterButtons = () => {\n const handleButtonClick = (operation) => {\n   counterSubject.next(operation);\n };\n\n\n return (\n   &lt;div>\n     &lt;button onClick={() => handleButtonClick(\"+\")}>+&lt;\/button>\n     &lt;button onClick={() => handleButtonClick(\"-\")}>-&lt;\/button>\n   &lt;\/div>\n );\n};\n\nconst CounterApp = () => {\n return (\n   &lt;div>\n     &lt;CounterDisplay \/>\n     &lt;CounterButtons \/>\n   &lt;\/div>\n );\n};<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Recoil<\/strong><\/h3>\n\n\n\n<p>Recoil to biblioteka, kt\u00f3ra dzia\u0142a poprzez przechowywanie stanu aplikacji w tzw. atomach. Atomy s\u0105 prostymi obiektami, kt\u00f3re zawieraj\u0105 aktualn\u0105 warto\u015b\u0107 stanu oraz funkcje, kt\u00f3re pozwalaj\u0105 na aktualizacj\u0119 warto\u015bci. Dzi\u0119ki temu \u0142atwo jest zarz\u0105dza\u0107 stanem aplikacji i aktualizowa\u0107 go w reakcji na interakcj\u0119 podejmowan\u0105 przez u\u017cytkownika lub inne zdarzenia. <\/p>\n\n\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">import React from \"react\";\nimport { useRecoilState, atom, RecoilRoot } from \"recoil\";\n\n\nconst counterState = atom({\n key: \"counterState\",\n default: 0,\n});\n\nconst CounterDisplay = () => {\n const [counter] = useRecoilState(counterState);\n\n return &lt;div>Counter: {counter}&lt;\/div>;\n}\n\nconst CounterButtons = () => {\n const [counter, setCounter] = useRecoilState(counterState);\n\n\n const increment = () => {\n   setCounter(counter + 1);\n };\n\n const decrement = () => {\n   setCounter(counter - 1);\n };\n\n return (\n   &lt;div>\n     &lt;button onClick={increment}>+&lt;\/button>\n     &lt;button onClick={decrement}>-&lt;\/button>\n   &lt;\/div>\n );\n}\n\nconst CounterApp = () => {\n return (\n   &lt;RecoilRoot>\n     &lt;CounterDisplay \/>\n     &lt;CounterButtons \/>\n   &lt;\/RecoilRoot>\n );\n};<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Zustand<\/strong><\/h3>\n\n\n\n<p>Zustand to lekka biblioteka do zarz\u0105dzania stanem w React, kt\u00f3ra wykorzystuje podstawowe funkcjonalno\u015bci React do przechowywania i aktualizowania stanu. Oferuje proste API i pozwala na tworzenie globalnego stanu, zarz\u0105dzanie stanem w komponentach, w\u0142asnych modu\u0142ach, tworzenie selektor\u00f3w i subskrypcji stanu. Jest szybka i wydajna, co sprawia, \u017ce dzia\u0142a dobrze nawet w du\u017cych aplikacjach.<\/p>\n\n\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">import React from \"react\";\nimport create from \"zustand\";\n\nconst useCounterStore = create((set) => ({\n counter: 0,\n incrementCounter: () => set((state) => ({ counter: state.counter + 1 })),\n decrementCounter: () => set((state) => ({ counter: state.counter - 1 })),\n}));\n\nconst CounterDisplay = () => {\n const counter = useCounterStore((state) => state.counter);\n\n return &lt;div>Counter: {counter}&lt;\/div>;\n}\n\nconst CounterButtons = () => {\n const { incrementCounter, decrementCounter } = useCounterStore();\n\n return (\n   &lt;div>\n     &lt;button onClick={incrementCounter}>+&lt;\/button>\n     &lt;button onClick={decrementCounter}>-&lt;\/button>\n   &lt;\/div>\n );\n}\n\nconst CounterApp = () => {\n return (\n   &lt;div>\n     &lt;CounterDisplay \/>\n     &lt;CounterButtons \/>\n   &lt;\/div>\n );\n};<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"Kt\u00f3re-rozwi\u0105zanie-wybra\u0107?\">Kt\u00f3re rozwi\u0105zanie wybra\u0107?<\/h2>\n\n\n\n<p>Wyb\u00f3r rozwi\u0105zania do zarz\u0105dzania stanem w React zale\u017cy od wielu czynnik\u00f3w, takich jak rozmiar i z\u0142o\u017cono\u015b\u0107 projektu, preferencje zespo\u0142u programistycznego, do\u015bwiadczenia z innymi bibliotekami i podej\u015bciami. Wi\u0119kszo\u015b\u0107 starszych projekt\u00f3w w React korzysta z biblioteki Redux, gdy\u017c by\u0142o to najpopularniejsze rozwi\u0105zanie, kt\u00f3re przyzwyczai\u0142o programist\u00f3w do swojego sposobu dzia\u0142ania. Redux jest bardzo popularny w\u015br\u00f3d wi\u0119kszych projekt\u00f3w i ma du\u017ce wsparcie spo\u0142eczno\u015bci, co mo\u017ce pom\u00f3c w rozwi\u0105zywaniu problem\u00f3w \u2013 nie jest jednak polecany w nowych projektach.<\/p>\n\n\n\n<p>Wed\u0142ug mnie, je\u015bli rozpoczynasz nowy projekt w React i potrzebujesz rozwi\u0105zania do zarz\u0105dzania stanem, to sugerowa\u0142bym rozwa\u017cenie Recoil lub Zustand. S\u0105 to biblioteki, kt\u00f3re <strong>zosta\u0142y opracowane z my\u015bl\u0105 o prostocie i \u0142atwo\u015bci u\u017cycia<\/strong>, co mo\u017ce by\u0107 szczeg\u00f3lnie wa\u017cne w nowym projekcie, w kt\u00f3rym chcesz skupi\u0107 si\u0119 na szybkim wdro\u017ceniu funkcjonalno\u015bci i ograniczeniu ilo\u015bci kodu. <strong>Recoil <\/strong>i <strong>Zustand <\/strong>pozwalaj\u0105 na tworzenie stanu przy u\u017cyciu hook\u00f3w, co u\u0142atwia integracj\u0119 z React i zmniejsza potrzeb\u0119 tworzenia dodatkowych plik\u00f3w. W przypadku Recoil mo\u017cesz r\u00f3wnie\u017c korzysta\u0107 z selektor\u00f3w, kt\u00f3re pozwalaj\u0105 na pobieranie tylko niezb\u0119dnych danych ze stanu, co mo\u017ce przyspieszy\u0107 renderowanie aplikacji.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"Zarz\u0105dzanie-stanem-aplikacji-\u2013-podsumowanie\">Zarz\u0105dzanie stanem aplikacji \u2013 podsumowanie<\/h2>\n\n\n\n<p>Podsumowuj\u0105c, wyb\u00f3r biblioteki do zarz\u0105dzania stanem w React powinien by\u0107 solidnie przeanalizowany i nie jest \u0142atwo odpowiedzie\u0107 na pytanie \u201ekt\u00f3re narz\u0119dzie wybra\u0107?\u201d. Je\u015bli priorytetem s\u0105 \u0142atwo\u015b\u0107 u\u017cycia i szybka implementacja funkcjonalno\u015bci, dobrym pomys\u0142em mo\u017ce by\u0107 wykorzystanie kt\u00f3rego\u015b z innych rozwi\u0105za\u0144 &#8211; na przyk\u0142ad Recoil lub Zustand. <\/p>\n\n\n\n<p>Je\u015bli zastanawiasz si\u0119 nad wyborem Reduxa, to warto jest przeanalizowa\u0107, czy projekt jest na tyle z\u0142o\u017cony i wymagaj\u0105cy, \u017ce jego zastosowanie jest potrzebne. Mo\u017ce si\u0119 te\u017c okaza\u0107, \u017ce projekt nie wymaga u\u017cycia \u017cadnej biblioteki do zarz\u0105dzania stanem, poniewa\u017c sam React dostarcza narz\u0119dzi do zarz\u0105dzania stanem w komponentach, kt\u00f3re s\u0105 wystarczaj\u0105ce dla prostych projekt\u00f3w<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Wi\u0119kszo\u015b\u0107 starszych projekt\u00f3w wykorzystuj\u0105cych React korzysta z biblioteki Redux. To popularne rozwi\u0105zanie, kt\u00f3re przyzwyczai\u0142o programist\u00f3w do okre\u015blonego sposobu dzia\u0142ania. W dodatku ma spor\u0105 spo\u0142eczno\u015b\u0107 u\u017cytkownik\u00f3w gotowych s\u0142u\u017cy\u0107 pomoc\u0105. Je\u015bli pracujesz w nowym projekcie, w kt\u00f3rym priorytetem jest szybko\u015b\u0107 wdra\u017cania i ograniczenie ilo\u015bci kodu, warto wzi\u0105\u0107 pod uwag\u0119 inne opcje. W artykule przedstawiam kilka intuicyjnych i \u0142atwych w obs\u0142udze narz\u0119dzi, kt\u00f3re z powodzeniem mog\u0105 konkurowa\u0107 z bibliotek\u0105 Redux. Kt\u00f3re wybra\u0107? Sprawd\u017a!<\/p>\n","protected":false},"author":190,"featured_media":30601,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"iawp_total_views":36,"footnotes":""},"categories":[1,582],"tags":[570],"offering":[522],"class_list":["post-30596","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-artykuly","category-technologie","tag-javascript-pl","offering-tech-blog"],"acf":[],"_links":{"self":[{"href":"https:\/\/nearshore-it.eu\/pl\/wp-json\/wp\/v2\/posts\/30596","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/nearshore-it.eu\/pl\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/nearshore-it.eu\/pl\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/nearshore-it.eu\/pl\/wp-json\/wp\/v2\/users\/190"}],"replies":[{"embeddable":true,"href":"https:\/\/nearshore-it.eu\/pl\/wp-json\/wp\/v2\/comments?post=30596"}],"version-history":[{"count":2,"href":"https:\/\/nearshore-it.eu\/pl\/wp-json\/wp\/v2\/posts\/30596\/revisions"}],"predecessor-version":[{"id":32943,"href":"https:\/\/nearshore-it.eu\/pl\/wp-json\/wp\/v2\/posts\/30596\/revisions\/32943"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/nearshore-it.eu\/pl\/wp-json\/wp\/v2\/media\/30601"}],"wp:attachment":[{"href":"https:\/\/nearshore-it.eu\/pl\/wp-json\/wp\/v2\/media?parent=30596"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/nearshore-it.eu\/pl\/wp-json\/wp\/v2\/categories?post=30596"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/nearshore-it.eu\/pl\/wp-json\/wp\/v2\/tags?post=30596"},{"taxonomy":"offering","embeddable":true,"href":"https:\/\/nearshore-it.eu\/pl\/wp-json\/wp\/v2\/offering?post=30596"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}