{"id":34704,"date":"2025-11-21T01:40:58","date_gmt":"2025-11-20T22:40:58","guid":{"rendered":"https:\/\/fatihsoysal.com\/blog\/?p=34704"},"modified":"2025-11-21T01:40:58","modified_gmt":"2025-11-20T22:40:58","slug":"redux-thunk-ile-asenkron-redux-eylemlerini-anlamak","status":"publish","type":"post","link":"https:\/\/fatihsoysal.com\/blog\/redux-thunk-ile-asenkron-redux-eylemlerini-anlamak\/","title":{"rendered":"Redux Thunk ile Asenkron Redux Eylemlerini Anlamak"},"content":{"rendered":"<p><body><\/p>\n<h2>Redux Thunk ile Asenkron Redux Eylemlerini Anlamak<\/h2>\n<h3>Giri\u015f: Redux ve Asenkronlu\u011fun Zorunlulu\u011fu<\/h3>\n<p>Modern web uygulamalar\u0131, kullan\u0131c\u0131 deneyimini zenginle\u015ftirmek ve verimlili\u011fi art\u0131rmak i\u00e7in s\u00fcrekli olarak sunucuyla ileti\u015fim kurar. Kullan\u0131c\u0131 verilerini \u00e7ekmek, form g\u00f6ndermek, dosya y\u00fcklemek veya anl\u0131k bildirimler almak gibi i\u015flemlerin tamam\u0131 asenkron olarak ger\u00e7ekle\u015fir. Bu t\u00fcr i\u015flemler, uygulaman\u0131n ana i\u015f par\u00e7ac\u0131\u011f\u0131n\u0131 (main thread) bloke etmeden arka planda y\u00fcr\u00fct\u00fcl\u00fcr, b\u00f6ylece kullan\u0131c\u0131 aray\u00fcz\u00fc (UI) donmaz ve ak\u0131c\u0131 bir deneyim sunulur.<\/p>\n<p>React uygulamalar\u0131nda durum y\u00f6netimini merkezi ve \u00f6ng\u00f6r\u00fclebilir bir \u015fekilde sa\u011flamak i\u00e7in Redux gibi k\u00fct\u00fcphaneler yayg\u0131n olarak kullan\u0131l\u0131r. Redux, uygulaman\u0131n t\u00fcm durumunu tek bir yerde (store) tutan, bu durumu yaln\u0131zca saf (pure) fonksiyonlar (indirgeyiciler\/reducers) arac\u0131l\u0131\u011f\u0131yla ve yaln\u0131zca eylemler (actions) ile de\u011fi\u015ftirilebilen bir mimari sunar. Bu prensipler, uygulaman\u0131n durumunu takip etmeyi, hatalar\u0131 ay\u0131klamay\u0131 ve test etmeyi kolayla\u015ft\u0131r\u0131r. Ancak Redux&#8217;\u0131n bu temel prensipleri, asenkron i\u015flemlerle do\u011fal olarak \u00e7eli\u015fir.<\/p>\n<p>Redux&#8217;\u0131n indirgeyicileri, verilen bir durum ve eylem i\u00e7in her zaman ayn\u0131 \u00e7\u0131kt\u0131y\u0131 \u00fcretmeli ve herhangi bir yan etki (side effect) i\u00e7ermemelidir. Yan etkiler, bir fonksiyonun d\u0131\u015f d\u00fcnyay\u0131 etkilemesi veya d\u0131\u015f d\u00fcnyadan etkilenmesi anlam\u0131na gelir; \u00f6rne\u011fin bir API \u00e7a\u011fr\u0131s\u0131 yapmak, bir zamanlay\u0131c\u0131 ayarlamak veya konsola \u00e7\u0131kt\u0131 yazmak gibi. Asenkron i\u015flemler do\u011fas\u0131 gere\u011fi yan etkiler i\u00e7erir ve bu nedenle do\u011frudan indirgeyiciler i\u00e7inde ele al\u0131namazlar. Eylemlerin ise sadece durumu tan\u0131mlayan d\u00fcz JavaScript nesneleri olmas\u0131 beklenir. Peki, bir API \u00e7a\u011fr\u0131s\u0131 gibi zaman al\u0131c\u0131 bir i\u015flemi Redux ak\u0131\u015f\u0131na nas\u0131l entegre edebiliriz? \u0130\u015fte bu noktada Redux middleware&#8217;leri ve \u00f6zellikle Redux Thunk devreye girer. Redux Thunk, Redux&#8217;\u0131n asenkron i\u015flemleri y\u00f6netme yetene\u011fini art\u0131ran basit ama g\u00fc\u00e7l\u00fc bir ara\u00e7t\u0131r. Bu makalede, Redux Thunk&#8217;\u0131n ne oldu\u011funu, nas\u0131l \u00e7al\u0131\u015ft\u0131\u011f\u0131n\u0131 ve asenkron Redux eylemlerini anlamak ve uygulamak i\u00e7in neden bu kadar \u00f6nemli oldu\u011funu detayl\u0131 bir \u015fekilde inceleyece\u011fiz.<\/p>\n<h3>Senkron Redux Eylemlerine H\u0131zl\u0131 Bir Bak\u0131\u015f<\/h3>\n<p>Redux&#8217;\u0131n temelini olu\u015fturan senkron eylem ak\u0131\u015f\u0131n\u0131 anlamak, asenkron eylemlerin neden \u00f6zel bir yakla\u015f\u0131ma ihtiya\u00e7 duydu\u011funu kavramak i\u00e7in kritik \u00f6neme sahiptir. Redux&#8217;ta, uygulaman\u0131n durumunu de\u011fi\u015ftirmek istedi\u011finizde a\u015fa\u011f\u0131daki ad\u0131mlar izlenir:<\/p>\n<p>1.  <strong>Eylem Yarat\u0131c\u0131s\u0131 (Action Creator)<\/strong>: Durumda bir de\u011fi\u015fiklik niyetini ifade eden bir fonksiyon tan\u0131mlars\u0131n\u0131z. Bu fonksiyon, bir &#8220;eylem&#8221; nesnesi d\u00f6nd\u00fcr\u00fcr.<\/p>\n<pre><code class=\"language-javascript\">function incrementCounter() {\n      return {\n        type: 'INCREMENT',\n        payload: 1\n      };\n    }<\/code><\/pre>\n<p>    Burada <code>incrementCounter<\/code> bir eylem yarat\u0131c\u0131s\u0131d\u0131r.<br \/>\n2.  <strong>Eylem (Action)<\/strong>: Eylem yarat\u0131c\u0131s\u0131n\u0131n d\u00f6nd\u00fcrd\u00fc\u011f\u00fc, <code>type<\/code> \u00f6zelli\u011fine sahip d\u00fcz bir JavaScript nesnesidir. <code>type<\/code> \u00f6zelli\u011fi, hangi t\u00fcr de\u011fi\u015fikli\u011fin yap\u0131laca\u011f\u0131n\u0131 belirtir. Genellikle <code>payload<\/code> gibi ek veriler de i\u00e7erebilir.<\/p>\n<pre><code class=\"language-javascript\">{ type: 'INCREMENT', payload: 1 }<\/code><\/pre>\n<p>    Bu, yukar\u0131daki eylem yarat\u0131c\u0131s\u0131n\u0131n d\u00f6nd\u00fcrd\u00fc\u011f\u00fc eylem nesnesidir.<br \/>\n3.  <strong><code>dispatch<\/code> Fonksiyonu<\/strong>: Bir bile\u015fenden veya ba\u015fka bir yerden, bu eylem nesnesini Redux store&#8217;una g\u00f6ndermek i\u00e7in <code>store.dispatch()<\/code> fonksiyonunu \u00e7a\u011f\u0131r\u0131rs\u0131n\u0131z.<\/p>\n<pre><code class=\"language-javascript\">store.dispatch(incrementCounter());<\/code><\/pre>\n<p>    Bu \u00e7a\u011fr\u0131, eylemi Redux ak\u0131\u015f\u0131na sokar.<br \/>\n4.  <strong>\u0130ndirgeyici (Reducer)<\/strong>: Redux store&#8217;u, kendisine g\u00f6nderilen eylemi al\u0131r ve bu eylemi t\u00fcm kay\u0131tl\u0131 indirgeyicilere iletir. Her indirgeyici, uygulaman\u0131n belirli bir b\u00f6l\u00fcm\u00fcn\u00fcn durumunu y\u00f6netir. Bir indirgeyici, mevcut durumu ve eylemi girdi olarak al\u0131r ve eyleme g\u00f6re <em>yeni bir durum nesnesi<\/em> d\u00f6nd\u00fcr\u00fcr. \u0130ndirgeyiciler saf fonksiyonlar olmal\u0131d\u0131r; yani yan etki i\u00e7ermemeli, do\u011frudan durumu de\u011fi\u015ftirmemeli (immutable olmal\u0131) ve her zaman ayn\u0131 girdi i\u00e7in ayn\u0131 \u00e7\u0131kt\u0131y\u0131 \u00fcretmelidir.<\/p>\n<pre><code class=\"language-javascript\">function counterReducer(state = { count: 0 }, action) {\n      switch (action.type) {\n        case 'INCREMENT':\n          return { ...state, count: state.count + action.payload };\n        case 'DECREMENT':\n          return { ...state, count: state.count - action.payload };\n        default:\n          return state;\n      }\n    }<\/code><\/pre>\n<p>5.  <strong>Yeni Durum (New State)<\/strong>: \u0130ndirgeyiciler yeni durumu d\u00f6nd\u00fcrd\u00fc\u011f\u00fcnde, Redux store&#8217;u g\u00fcncellenir. Bu g\u00fcncelleme, Redux&#8217;a ba\u011fl\u0131 t\u00fcm bile\u015fenlerin (\u00f6rne\u011fin React bile\u015fenleri <code>useSelector<\/code> hook&#8217;u ile) yeniden render edilmesine neden olabilir, b\u00f6ylece UI yeni durumu yans\u0131t\u0131r.<\/p>\n<p>Bu ak\u0131\u015f tamamen senkrondur ve her ad\u0131m an\u0131nda ger\u00e7ekle\u015fir. Eylem nesnesi olu\u015fturulur, g\u00f6nderilir, indirgeyici taraf\u0131ndan i\u015flenir ve durum g\u00fcncellenir; bunlar\u0131n hepsi tek bir olay d\u00f6ng\u00fcs\u00fc i\u00e7inde tamamlan\u0131r.<\/p>\n<h3>Redux&#8217;ta Asenkronlu\u011fun Zorluklar\u0131<\/h3>\n<p>Redux&#8217;\u0131n temel prensipleri, uygulaman\u0131n durumunu \u00f6ng\u00f6r\u00fclebilir ve izlenebilir k\u0131lmak i\u00e7in tasarlanm\u0131\u015ft\u0131r. Ancak bu prensipler, asenkron i\u015flemlerle kar\u015f\u0131la\u015f\u0131ld\u0131\u011f\u0131nda do\u011fal zorluklar yarat\u0131r:<\/p>\n<p>1.  <strong>\u0130ndirgeyicilerin Safl\u0131\u011f\u0131 (Purity of Reducers)<\/strong>: Redux&#8217;\u0131n en temel kurallar\u0131ndan biri, indirgeyicilerin saf fonksiyonlar olmas\u0131d\u0131r. Saf fonksiyonlar:<br \/>\n    *   Ayn\u0131 girdilerle \u00e7a\u011fr\u0131ld\u0131\u011f\u0131nda her zaman ayn\u0131 \u00e7\u0131kt\u0131y\u0131 \u00fcretirler.<br \/>\n    *   D\u0131\u015f d\u00fcnyay\u0131 etkileyen veya d\u0131\u015f d\u00fcnyadan etkilenen herhangi bir yan etki (side effect) i\u00e7ermezler.<br \/>\n    *   Girdilerini do\u011frudan de\u011fi\u015ftirmezler (immutable olmal\u0131d\u0131rlar).<\/p>\n<p>    Bir API \u00e7a\u011fr\u0131s\u0131 yapmak, bir <code>setTimeout<\/code> kullanmak veya bir veritaban\u0131 sorgusu \u00e7al\u0131\u015ft\u0131rmak gibi asenkron i\u015flemlerin hepsi yan etkilerdir. Bu i\u015flemlerin sonucu zamanla de\u011fi\u015febilir, d\u0131\u015f kaynaklara ba\u011f\u0131ml\u0131d\u0131r ve genellikle tahmin edilemez bir s\u00fcre al\u0131r. Bu nedenle, bir API \u00e7a\u011fr\u0131s\u0131n\u0131 do\u011frudan bir indirgeyici i\u00e7inde yapmak, indirgeyicinin safl\u0131k ilkesini ihlal eder ve Redux&#8217;\u0131n temel mimarisini bozar.<\/p>\n<p>2.  <strong>Eylemlerin D\u00fcz Nesneler Olmas\u0131 Gereklili\u011fi<\/strong>: Redux&#8217;ta, <code>dispatch<\/code> fonksiyonuna g\u00f6nderilen eylemlerin basit, d\u00fcz JavaScript nesneleri olmas\u0131 beklenir. Bu nesneler, <code>type<\/code> \u00f6zelli\u011fi arac\u0131l\u0131\u011f\u0131yla ne t\u00fcr bir de\u011fi\u015fikli\u011fin yap\u0131laca\u011f\u0131n\u0131 belirtir ve iste\u011fe ba\u011fl\u0131 olarak <code>payload<\/code> gibi ek veriler i\u00e7erebilir. Eylemlerin d\u00fcz nesneler olmas\u0131, seri hale getirilmelerini (serialize) ve zaman yolculu\u011fu hata ay\u0131klama (time-travel debugging) gibi Redux DevTools \u00f6zelliklerinin d\u00fczg\u00fcn \u00e7al\u0131\u015fmas\u0131n\u0131 sa\u011flar.<\/p>\n<p>    Bir API \u00e7a\u011fr\u0131s\u0131 gibi asenkron bir i\u015flemi temsil eden bir eylemin d\u00fcz bir nesne olmas\u0131 m\u00fcmk\u00fcn de\u011fildir. Bir API \u00e7a\u011fr\u0131s\u0131, iste\u011fi ba\u015flatma, veriyi bekleme ve ba\u015far\u0131l\u0131 veya ba\u015far\u0131s\u0131z olma gibi birden fazla a\u015famadan ge\u00e7er. Bu a\u015famalar\u0131n her biri farkl\u0131 bir durumu veya olay\u0131 temsil eder ve tek bir d\u00fcz nesneyle ifade edilemez.<\/p>\n<p><strong>Problem \u00d6zeti<\/strong>: Bir kullan\u0131c\u0131 listesini sunucudan \u00e7ekmek istedi\u011fimizi varsayal\u0131m. Bu i\u015flem \u015fu ad\u0131mlar\u0131 i\u00e7erecektir:<br \/>\n*   Kullan\u0131c\u0131 verisi \u00e7ekme iste\u011fini ba\u015flatma.<br \/>\n*   API \u00e7a\u011fr\u0131s\u0131n\u0131n sonucunu bekleme.<br \/>\n*   API \u00e7a\u011fr\u0131s\u0131 ba\u015far\u0131l\u0131 olursa, gelen veriyi Redux store&#8217;a kaydetme.<br \/>\n*   API \u00e7a\u011fr\u0131s\u0131 ba\u015far\u0131s\u0131z olursa, hatay\u0131 Redux store&#8217;a kaydetme.<\/p>\n<p>Bu ad\u0131mlar\u0131n her biri, farkl\u0131 bir Redux eylemi gerektirebilir (<code>FETCH_USERS_REQUEST<\/code>, <code>FETCH_USERS_SUCCESS<\/code>, <code>FETCH_USERS_FAILURE<\/code>). Ancak bu eylemleri ne zaman <code>dispatch<\/code> edece\u011fiz? API \u00e7a\u011fr\u0131s\u0131n\u0131n kendisi nerede yap\u0131lacak? Do\u011frudan <code>dispatch<\/code> \u00e7a\u011fr\u0131s\u0131ndan \u00f6nce mi? Yoksa bir indirgeyici i\u00e7inde mi? Bu sorular, Redux&#8217;\u0131n asenkron i\u015flemler i\u00e7in do\u011frudan bir mekanizma sunmad\u0131\u011f\u0131n\u0131 ve bir k\u00f6pr\u00fcye ihtiya\u00e7 duyuldu\u011funu a\u00e7\u0131k\u00e7a g\u00f6sterir.<\/p>\n<h3>Middleware Kavram\u0131: Redux Ak\u0131\u015f\u0131ndaki K\u00f6pr\u00fc<\/h3>\n<p>Redux&#8217;ta asenkron i\u015flemlerin ve di\u011fer yan etkilerin y\u00f6netilmesi i\u00e7in kullan\u0131lan temel mekanizma &#8220;middleware&#8221;dir. Middleware, Redux&#8217;\u0131n <code>dispatch<\/code> fonksiyonuna g\u00f6nderilen eylemler ile bu eylemlerin indirgeyicilere ula\u015fmas\u0131 aras\u0131na yerle\u015fen bir katmand\u0131r. Bir middleware, bir eylemi yakalayabilir, \u00fczerinde de\u011fi\u015fiklik yapabilir, bir \u015feyleri loglayabilir, API \u00e7a\u011fr\u0131lar\u0131 ba\u015flatabilir, ba\u015fka eylemler <code>dispatch<\/code> edebilir ve hatta eylemin indirgeyicilere ula\u015fmas\u0131n\u0131 engelleyebilir.<\/p>\n<p><strong>Middleware Nas\u0131l \u00c7al\u0131\u015f\u0131r?<\/strong><\/p>\n<p>Redux&#8217;\u0131n <code>dispatch<\/code> fonksiyonu, bir eylemi do\u011frudan indirgeyicilere g\u00f6ndermeden \u00f6nce middleware zincirinden ge\u00e7irir. Her middleware, bir eylemi i\u015fleme yetene\u011fine sahiptir ve bir sonraki middleware&#8217;e (veya zincirin sonundaysa indirgeyicilere) eylemi iletmek i\u00e7in bir <code>next<\/code> fonksiyonu sa\u011flar.<\/p>\n<p>Bir middleware&#8217;in yap\u0131s\u0131 genellikle \u015fu \u015fekildedir:<\/p>\n<pre><code class=\"language-javascript\">const myMiddleware = store => next => action => {\n  \/\/ Eylem indirgeyicilere ula\u015fmadan \u00f6nce burada bir \u015feyler yapabiliriz\n  console.log('Dispatch edilen eylem:', action.type);\n\n  \/\/ Eylemi bir sonraki middleware'e veya indirgeyicilere ilet\n  const result = next(action);\n\n  \/\/ Eylem i\u015flendikten sonra burada bir \u015feyler yapabiliriz\n  console.log('Yeni durum:', store.getState());\n\n  return result;\n};<\/code><\/pre>\n<p>*   <code>store<\/code>: <code>getState()<\/code> ve <code>dispatch()<\/code> gibi store metotlar\u0131na eri\u015fim sa\u011flar.<br \/>\n*   <code>next<\/code>: Zincirdeki bir sonraki middleware&#8217;i (veya en sondaysa orijinal <code>dispatch<\/code> fonksiyonunu) temsil eden fonksiyondur. Eylemi <code>next(action)<\/code> ile \u00e7a\u011f\u0131rarak zincirde ilerletiriz.<br \/>\n*   <code>action<\/code>: <code>dispatch<\/code> edilen mevcut eylem nesnesidir.<\/p>\n<p>Bu yap\u0131 sayesinde middleware&#8217;ler, Redux&#8217;\u0131n tek y\u00f6nl\u00fc veri ak\u0131\u015f\u0131n\u0131 bozmadan, eylemleri yakalayabilir ve yan etkileri y\u00f6netebilir. Asenkron i\u015flemler i\u00e7in Redux Thunk gibi middleware&#8217;ler, eylem yarat\u0131c\u0131lar\u0131n\u0131n d\u00fcz nesneler yerine fonksiyonlar d\u00f6nd\u00fcrmesine izin vererek bu k\u00f6pr\u00fc g\u00f6revini \u00fcstlenir.<\/p>\n<h3>Redux Thunk&#8217;\u0131 Tan\u0131yal\u0131m<\/h3>\n<p>Redux Thunk, Redux i\u00e7in en pop\u00fcler ve en basit middleware&#8217;lerden biridir. Temel amac\u0131, Redux&#8217;\u0131n asenkron i\u015flemleri do\u011fal bir \u015fekilde y\u00f6netmesini sa\u011flamakt\u0131r. Bunu, eylem yarat\u0131c\u0131lar\u0131n\u0131n d\u00fcz JavaScript nesneleri d\u00f6nd\u00fcrmek yerine <em>fonksiyonlar<\/em> d\u00f6nd\u00fcrmesine izin vererek yapar.<\/p>\n<p><strong>Thunk Nedir?<\/strong><\/p>\n<p>Bilgisayar biliminde &#8220;thunk&#8221;, bir hesaplamay\u0131 erteleyen bir fonksiyonu ifade eder. Yani, bir fonksiyonun de\u011ferini hemen hesaplamak yerine, bu de\u011feri hesaplayacak bir fonksiyon d\u00f6nd\u00fcr\u00fcrs\u00fcn\u00fcz. De\u011fer, bu d\u00f6nd\u00fcr\u00fclen fonksiyon \u00e7a\u011fr\u0131ld\u0131\u011f\u0131nda hesaplan\u0131r. Redux Thunk ba\u011flam\u0131nda, bu, bir eylemi hemen <code>dispatch<\/code> etmek yerine, asenkron bir i\u015flem tamamland\u0131\u011f\u0131nda <code>dispatch<\/code> edilecek bir fonksiyon d\u00f6nd\u00fcrmek anlam\u0131na gelir.<\/p>\n<p><strong>Redux Thunk Nas\u0131l \u00c7al\u0131\u015f\u0131r?<\/strong><\/p>\n<p>Redux Thunk middleware&#8217;i, <code>dispatch<\/code> edilen her eylemi kontrol eder:<br \/>\n1.  <strong>D\u00fcz Nesne \u0130se<\/strong>: E\u011fer <code>dispatch<\/code> edilen \u015fey d\u00fcz bir JavaScript nesnesiyse (yani senkron bir eylemse), Thunk middleware&#8217;i onu es ge\u00e7er ve bir sonraki middleware&#8217;e veya do\u011frudan indirgeyicilere iletir.<br \/>\n2.  <strong>Fonksiyon \u0130se<\/strong>: E\u011fer <code>dispatch<\/code> edilen \u015fey bir fonksiyonsa (yani bir thunk eylemiyse), Thunk middleware&#8217;i bu fonksiyonu \u00e7a\u011f\u0131r\u0131r. Bu fonksiyon, iki arg\u00fcman al\u0131r:<br \/>\n    *   <code>dispatch<\/code>: Redux store&#8217;unun <code>dispatch<\/code> fonksiyonu. Bu sayede thunk i\u00e7inde ba\u015fka eylemler <code>dispatch<\/code> edilebilir (\u00f6rne\u011fin, API iste\u011finin ba\u015flad\u0131\u011f\u0131n\u0131, ba\u015far\u0131l\u0131 oldu\u011funu veya ba\u015far\u0131s\u0131z oldu\u011funu belirten eylemler).<br \/>\n    *   <code>getState<\/code>: Redux store&#8217;unun <code>getState<\/code> fonksiyonu. Bu, thunk i\u00e7inde mevcut Redux durumuna eri\u015fim sa\u011flar. B\u00f6ylece, mevcut duruma g\u00f6re ko\u015fullu mant\u0131k y\u00fcr\u00fct\u00fclebilir.<\/p>\n<p>Bu mekanizma, thunk fonksiyonunun i\u00e7inde yan etkileri (API \u00e7a\u011fr\u0131lar\u0131, zamanlay\u0131c\u0131lar vb.) g\u00fcvenle ger\u00e7ekle\u015ftirmesine ve bu yan etkilerin sonucuna g\u00f6re Redux store&#8217;unu g\u00fcncellemek i\u00e7in birden fazla eylemi <code>dispatch<\/code> etmesine olanak tan\u0131r.<\/p>\n<p><strong>Neden G\u00fc\u00e7l\u00fc?<\/strong><\/p>\n<p>*   <strong>Yan Etkileri Y\u00f6netme<\/strong>: Thunk i\u00e7inde API \u00e7a\u011fr\u0131lar\u0131 gibi yan etkileri g\u00fcvenle ger\u00e7ekle\u015ftirebilirsiniz.<br \/>\n*   <strong>Birden Fazla <code>dispatch<\/code><\/strong>: Tek bir asenkron i\u015flem s\u0131ras\u0131nda birden fazla eylem (<code>REQUEST<\/code>, <code>SUCCESS<\/code>, <code>FAILURE<\/code> gibi) <code>dispatch<\/code> edebilirsiniz.<br \/>\n*   <strong>Ko\u015fullu Mant\u0131k<\/strong>: <code>getState<\/code> arg\u00fcman\u0131n\u0131 kullanarak mevcut duruma g\u00f6re ko\u015fullu i\u015flemler yapabilir veya belirli bir verinin zaten store&#8217;da olup olmad\u0131\u011f\u0131n\u0131 kontrol edebilirsiniz.<br \/>\n*   <strong>Basitlik<\/strong>: Di\u011fer asenkron middleware&#8217;lerine k\u0131yasla (\u00f6rne\u011fin Redux Saga veya Redux Observable) \u00f6\u011frenme e\u011frisi \u00e7ok daha d\u00fc\u015f\u00fckt\u00fcr. JavaScript&#8217;in temel asenkron \u00f6zelliklerini (Promise&#8217;ler, <code>async\/await<\/code>) do\u011frudan kullan\u0131r.<\/p>\n<h3>Redux Thunk Uygulamas\u0131: Ad\u0131m Ad\u0131m<\/h3>\n<p>Redux Thunk&#8217;\u0131 bir Redux projesine entegre etmek ve kullanmak olduk\u00e7a basittir. \u0130\u015fte ad\u0131m ad\u0131m bir rehber:<\/p>\n<h4>1. Kurulum<\/h4>\n<p>\u00d6ncelikle Redux Thunk paketini projenize kurman\u0131z gerekir:<\/p>\n<pre><code class=\"language-bash\">npm install redux-thunk\n<h2>veya<\/h2>\nyarn add redux-thunk<\/code><\/pre>\n<h4>2. Middleware&#8217;i Redux Store&#8217;una Uygulama<\/h4>\n<p>Redux Thunk&#8217;\u0131 kullanabilmek i\u00e7in, onu Redux store&#8217;unuza bir middleware olarak uygulaman\u0131z gerekir. Bu i\u015flem genellikle <code>createStore<\/code> (geleneksel Redux) veya <code>configureStore<\/code> (Redux Toolkit ile \u00f6nerilen) fonksiyonlar\u0131 arac\u0131l\u0131\u011f\u0131yla yap\u0131l\u0131r.<\/p>\n<p><strong>Geleneksel Redux ile:<\/strong><\/p>\n<pre><code class=\"language-javascript\">import { createStore, applyMiddleware } from 'redux';\nimport { thunk } from 'redux-thunk'; \/\/ ES6 mod\u00fcl\u00fcnden thunk'\u0131 i\u00e7e aktar\u0131n\nimport rootReducer from '.\/reducers'; \/\/ K\u00f6k indirgeyiciniz\n\nconst store = createStore(\n  rootReducer,\n  applyMiddleware(thunk) \/\/ Redux Thunk'\u0131 middleware olarak uygulay\u0131n\n);\n\nexport default store;<\/code><\/pre>\n<p><strong>Redux Toolkit ile (\u00d6nerilen):<\/strong><\/p>\n<p>Redux Toolkit, Redux uygulamalar\u0131n\u0131 daha kolay ve verimli hale getirmek i\u00e7in tasarlanm\u0131\u015ft\u0131r. <code>configureStore<\/code> fonksiyonu, varsay\u0131lan olarak <code>redux-thunk<\/code> ve di\u011fer baz\u0131 faydal\u0131 middleware&#8217;leri i\u00e7erir, bu y\u00fczden genellikle manuel olarak eklemeniz gerekmez.<\/p>\n<pre><code class=\"language-javascript\">import { configureStore } from '@reduxjs\/toolkit';\nimport rootReducer from '.\/reducers'; \/\/ K\u00f6k indirgeyiciniz\n\nconst store = configureStore({\n  reducer: rootReducer,\n  \/\/ middleware'i manuel olarak eklemeniz gerekmez, configureStore varsay\u0131lan olarak thunk'\u0131 i\u00e7erir.\n  \/\/ Ancak, \u00f6zel bir middleware eklemek veya varsay\u0131lanlar\u0131 de\u011fi\u015ftirmek isterseniz:\n  \/\/ middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(myCustomMiddleware),\n});\n\nexport default store;<\/code><\/pre>\n<h4>3. \u00d6rnek Senaryo: Kullan\u0131c\u0131 Verisi \u00c7ekme (API \u00c7a\u011fr\u0131s\u0131)<\/h4>\n<p>\u015eimdi, bir API&#8217;den kullan\u0131c\u0131 verisi \u00e7eken asenkron bir Redux eylemi olu\u015ftural\u0131m. Bu i\u015flem genellikle \u00fc\u00e7 farkl\u0131 durumu i\u00e7erir: iste\u011fin ba\u015flamas\u0131, iste\u011fin ba\u015far\u0131yla tamamlanmas\u0131 ve iste\u011fin ba\u015far\u0131s\u0131z olmas\u0131. Bu durumlar\u0131n her birini ele almak i\u00e7in farkl\u0131 eylem tipleri tan\u0131mlayaca\u011f\u0131z.<\/p>\n<p><strong>a. Eylem Tipleri (Action Types)<\/strong><\/p>\n<pre><code class=\"language-javascript\">\/\/ actions\/userTypes.js\nexport const FETCH_USERS_REQUEST = 'FETCH_USERS_REQUEST';\nexport const FETCH_USERS_SUCCESS = 'FETCH_USERS_SUCCESS';\nexport const FETCH_USERS_FAILURE = 'FETCH_USERS_FAILURE';<\/code><\/pre>\n<p><strong>b. \u0130ndirgeyici (Reducer)<\/strong><\/p>\n<p>Bu eylem tiplerini ele alacak bir indirgeyiciye ihtiyac\u0131m\u0131z var. Bu indirgeyici, kullan\u0131c\u0131 verilerini, y\u00fckleme durumunu ve hata mesajlar\u0131n\u0131 store&#8217;da tutacakt\u0131r.<\/p>\n<pre><code class=\"language-javascript\">\/\/ reducers\/userReducer.js\nimport {\n  FETCH_USERS_REQUEST,\n  FETCH_USERS_SUCCESS,\n  FETCH_USERS_FAILURE,\n} from '..\/actions\/userTypes';\n\nconst initialState = {\n  loading: false,\n  users: [],\n  error: '',\n};\n\nconst userReducer = (state = initialState, action) => {\n  switch (action.type) {\n    case FETCH_USERS_REQUEST:\n      return {\n        ...state,\n        loading: true,\n      };\n    case FETCH_USERS_SUCCESS:\n      return {\n        ...state,\n        loading: false,\n        users: action.payload,\n        error: '',\n      };\n    case FETCH_USERS_FAILURE:\n      return {\n        ...state,\n        loading: false,\n        users: [],\n        error: action.payload,\n      };\n    default:\n      return state;\n  }\n};\n\nexport default userReducer;<\/code><\/pre>\n<p><strong>c. Asenkron Eylem Yarat\u0131c\u0131s\u0131 (Thunk Action Creator)<\/strong><\/p>\n<p>\u015eimdi as\u0131l Redux Thunk fonksiyonumuzu yazal\u0131m. Bu fonksiyon, bir API \u00e7a\u011fr\u0131s\u0131 yapacak ve duruma g\u00f6re ilgili eylemleri <code>dispatch<\/code> edecektir.<\/p>\n<pre><code class=\"language-javascript\">\/\/ actions\/userActions.js\nimport axios from 'axios'; \/\/ API \u00e7a\u011fr\u0131lar\u0131 i\u00e7in axios kullanaca\u011f\u0131z\nimport {\n  FETCH_USERS_REQUEST,\n  FETCH_USERS_SUCCESS,\n  FETCH_USERS_FAILURE,\n} from '.\/userTypes';\n\n\/\/ Normal eylem yarat\u0131c\u0131lar\u0131 (d\u00fcz nesneler d\u00f6nd\u00fcr\u00fcr)\nexport const fetchUsersRequest = () => ({\n  type: FETCH_USERS_REQUEST,\n});\n\nexport const fetchUsersSuccess = (users) => ({\n  type: FETCH_USERS_SUCCESS,\n  payload: users,\n});\n\nexport const fetchUsersFailure = (error) => ({\n  type: FETCH_USERS_FAILURE,\n  payload: error,\n});\n\n\/\/ THUNK EYLEM YARATICISI\nexport const fetchUsers = () => {\n  return async (dispatch) => { \/\/ Redux Thunk sayesinde bu fonksiyonu dispatch edebiliriz\n    dispatch(fetchUsersRequest()); \/\/ \u0130stek ba\u015flad\u0131\u011f\u0131nda y\u00fckleme durumunu ayarla\n    try {\n      const response = await axios.get('https:\/\/jsonplaceholder.typicode.com\/users');\n      const users = response.data;\n      dispatch(fetchUsersSuccess(users)); \/\/ Ba\u015far\u0131l\u0131 oldu\u011funda kullan\u0131c\u0131lar\u0131 store'a kaydet\n    } catch (error) {\n      dispatch(fetchUsersFailure(error.message)); \/\/ Hata oldu\u011funda hata mesaj\u0131n\u0131 kaydet\n    }\n  };\n};<\/code><\/pre>\n<p><strong>A\u00e7\u0131klama:<\/strong><br \/>\n<em>   <code>fetchUsers<\/code> fonksiyonu, bir <\/em>ba\u015fka fonksiyon* d\u00f6nd\u00fcr\u00fcyor. \u0130\u015fte bu d\u00f6nd\u00fcr\u00fclen fonksiyon bir &#8220;thunk&#8221;t\u0131r.<br \/>\n*   Bu i\u00e7 fonksiyon <code>dispatch<\/code> ve <code>getState<\/code> arg\u00fcmanlar\u0131n\u0131 al\u0131r (bu \u00f6rnekte <code>getState<\/code> kullanmad\u0131k, ancak ihtiyac\u0131m\u0131z olsayd\u0131 eri\u015febilirdik).<br \/>\n*   \u0130\u00e7 fonksiyonun i\u00e7inde, \u00f6nce <code>fetchUsersRequest()<\/code> eylemini <code>dispatch<\/code> ederek y\u00fckleme durumunu <code>true<\/code> yapar\u0131z.<br \/>\n*   Ard\u0131ndan <code>axios.get()<\/code> ile asenkron bir API \u00e7a\u011fr\u0131s\u0131 yapar\u0131z. <code>async\/await<\/code> kullanarak kodu daha okunabilir hale getirdik.<br \/>\n*   API \u00e7a\u011fr\u0131s\u0131 ba\u015far\u0131l\u0131 olursa, <code>fetchUsersSuccess()<\/code> eylemini <code>dispatch<\/code> ederek gelen kullan\u0131c\u0131 verilerini store&#8217;a kaydederiz.<br \/>\n*   API \u00e7a\u011fr\u0131s\u0131 ba\u015far\u0131s\u0131z olursa, <code>fetchUsersFailure()<\/code> eylemini <code>dispatch<\/code> ederek hata mesaj\u0131n\u0131 store&#8217;a kaydederiz.<\/p>\n<h4>4. Bile\u015fen (Component) \u0130\u00e7inden Kullan\u0131m<\/h4>\n<p>Son olarak, bu thunk eylemini bir React bile\u015feni i\u00e7inden nas\u0131l \u00e7a\u011f\u0131raca\u011f\u0131m\u0131z\u0131 g\u00f6relim. <code>react-redux<\/code> k\u00fct\u00fcphanesinin <code>useDispatch<\/code> ve <code>useSelector<\/code> hook&#8217;lar\u0131n\u0131 kullanaca\u011f\u0131z.<\/p>\n<pre><code class=\"language-javascript\">\/\/ components\/UserList.js\nimport React, { useEffect } from 'react';\nimport { useSelector, useDispatch } from 'react-redux';\nimport { fetchUsers } from '..\/actions\/userActions';\n\nfunction UserList() {\n  const dispatch = useDispatch();\n  const userData = useSelector((state) => state.user); \/\/ userReducer'\u0131n y\u00f6netti\u011fi state'i al\n\n  useEffect(() => {\n    dispatch(fetchUsers()); \/\/ Bile\u015fen y\u00fcklendi\u011finde kullan\u0131c\u0131lar\u0131 \u00e7ekmek i\u00e7in thunk'\u0131 dispatch et\n  }, [dispatch]); \/\/ dispatch fonksiyonu de\u011fi\u015fmedi\u011fi i\u00e7in tek seferlik \u00e7al\u0131\u015f\u0131r\n\n  if (userData.loading) {\n    return <h2>Kullan\u0131c\u0131lar y\u00fckleniyor...<\/h2>;\n  }\n\n  if (userData.error) {\n    return <h2>Hata: {userData.error}<\/h2>;\n  }\n\n  return (\n    <div>\n      <h2>Kullan\u0131c\u0131 Listesi<\/h2>\n      <ul>\n        {userData.users.map((user) => (\n          <li key={user.id}>{user.name}<\/li>\n        ))}\n      <\/ul>\n    <\/div>\n  );\n}\n\nexport default UserList;<\/code><\/pre>\n<p>Bu \u00f6rnek, Redux Thunk&#8217;\u0131n asenkron bir API \u00e7a\u011fr\u0131s\u0131n\u0131 Redux ak\u0131\u015f\u0131na nas\u0131l sorunsuz bir \u015fekilde entegre etti\u011fini g\u00f6stermektedir. Kullan\u0131c\u0131 aray\u00fcz\u00fc, y\u00fckleme, ba\u015far\u0131 ve hata durumlar\u0131n\u0131 store&#8217;daki duruma g\u00f6re dinamik olarak g\u00fcnceller.<\/p>\n<h3>\u0130leri Thunk Desenleri ve En \u0130yi Uygulamalar<\/h3>\n<p>Redux Thunk&#8217;\u0131n temel kullan\u0131m\u0131 basit olsa da, daha karma\u015f\u0131k senaryolar i\u00e7in baz\u0131 ileri desenler ve en iyi uygulamalar mevcuttur.<\/p>\n<h4>1. <code>getState<\/code> Kullan\u0131m\u0131 ile Ko\u015fullu Mant\u0131k<\/h4>\n<p>Thunk fonksiyonlar\u0131, <code>dispatch<\/code> ile birlikte <code>getState<\/code> fonksiyonunu da arg\u00fcman olarak al\u0131r. Bu, mevcut Redux durumuna eri\u015fmenizi ve buna g\u00f6re ko\u015fullu mant\u0131k y\u00fcr\u00fctmenizi sa\u011flar.<\/p>\n<p><strong>\u00d6rnek: Veri Tekrar \u00c7ekmeyi Engelleme<\/strong><\/p>\n<p>Diyelim ki bir kullan\u0131c\u0131n\u0131n verilerini \u00e7ekmek istiyorsunuz, ancak bu veriler zaten store&#8217;da mevcutsa API \u00e7a\u011fr\u0131s\u0131 yapmaktan ka\u00e7\u0131nmak istiyorsunuz.<\/p>\n<pre><code class=\"language-javascript\">export const fetchUserIfNeeded = (userId) => {\n  return async (dispatch, getState) => {\n    const state = getState();\n    const user = state.users.data[userId]; \/\/ Kullan\u0131c\u0131n\u0131n store'da olup olmad\u0131\u011f\u0131n\u0131 kontrol et\n\n    if (user && !state.users.loading) { \/\/ Kullan\u0131c\u0131 varsa ve y\u00fcklenmiyorsa tekrar \u00e7ekme\n      return;\n    }\n\n    \/\/ E\u011fer kullan\u0131c\u0131 yoksa veya y\u00fckleniyorsa, \u00e7ekme i\u015flemini ba\u015flat\n    dispatch(fetchUserRequest());\n    try {\n      const response = await axios.get(<code>\/api\/users\/${userId}<\/code>);\n      dispatch(fetchUserSuccess(response.data));\n    } catch (error) {\n      dispatch(fetchUserFailure(error.message));\n    }\n  };\n};<\/code><\/pre>\n<p>Bu desen, gereksiz a\u011f isteklerini \u00f6nleyerek uygulaman\u0131z\u0131n performans\u0131n\u0131 art\u0131rabilir.<\/p>\n<h4>2. Thunk&#8217;lar\u0131 Zincirleme (Chaining Thunks)<\/h4>\n<p>Bir thunk i\u00e7inde ba\u015fka bir thunk&#8217;\u0131 <code>dispatch<\/code> edebilirsiniz. Bu, daha b\u00fcy\u00fck ve karma\u015f\u0131k asenkron i\u015f ak\u0131\u015flar\u0131n\u0131 daha k\u00fc\u00e7\u00fck, y\u00f6netilebilir par\u00e7alara b\u00f6lmek i\u00e7in faydal\u0131 olabilir. Ancak, bu yakla\u015f\u0131m dikkatli kullan\u0131lmal\u0131, aksi takdirde kod karma\u015f\u0131kl\u0131\u011f\u0131 artabilir.<\/p>\n<p><strong>\u00d6rnek: Kullan\u0131c\u0131 Olu\u015fturma ve Ard\u0131ndan T\u00fcm Kullan\u0131c\u0131lar\u0131 Yeniden \u00c7ekme<\/strong><\/p>\n<pre><code class=\"language-javascript\">export const createUser = (userData) => {\n  return async (dispatch) => {\n    dispatch(createUserRequest());\n    try {\n      await axios.post('\/api\/users', userData);\n      dispatch(createUserSuccess());\n      dispatch(fetchUsers()); \/\/ Yeni kullan\u0131c\u0131 olu\u015fturulduktan sonra t\u00fcm kullan\u0131c\u0131 listesini yeniden \u00e7ek\n    } catch (error) {\n      dispatch(createUserFailure(error.message));\n    }\n  };\n};<\/code><\/pre>\n<p>Bu desen, bir i\u015flemin tamamlanmas\u0131n\u0131n ard\u0131ndan ba\u015fka bir i\u015flemin tetiklenmesini sa\u011flar.<\/p>\n<h4>3. Kod Organizasyonu<\/h4>\n<p>B\u00fcy\u00fck uygulamalarda, eylem tiplerini, eylem yarat\u0131c\u0131lar\u0131n\u0131 ve thunk&#8217;lar\u0131 mant\u0131ksal olarak d\u00fczenlemek \u00f6nemlidir. Genellikle her \u00f6zellik alan\u0131 (feature) i\u00e7in ayr\u0131 bir klas\u00f6r olu\u015fturulur ve i\u00e7inde <code>actions.js<\/code>, <code>reducers.js<\/code>, <code>types.js<\/code> gibi dosyalar bulunur.<\/p>\n<pre><code class=\"language-\">src\/\n\u251c\u2500\u2500 features\/\n\u2502   \u2514\u2500\u2500 users\/\n\u2502       \u251c\u2500\u2500 actions.js    \/\/ Thunk'lar ve normal eylem yarat\u0131c\u0131lar\u0131\n\u2502       \u251c\u2500\u2500 reducers.js   \/\/ Kullan\u0131c\u0131 indirgeyicisi\n\u2502       \u2514\u2500\u2500 types.js      \/\/ Eylem tipleri\n\u251c\u2500\u2500 store\/\n\u2502   \u2514\u2500\u2500 index.js          \/\/ Store konfig\u00fcrasyonu\n\u2514\u2500\u2500 App.js<\/code><\/pre>\n<p>Redux Toolkit ile bu organizasyon genellikle <code>createSlice<\/code> kullan\u0131larak daha da basitle\u015ftirilir, \u00e7\u00fcnk\u00fc dilimler (slices) eylem tiplerini, eylem yarat\u0131c\u0131lar\u0131n\u0131 ve indirgeyicileri tek bir yerde birle\u015ftirir.<\/p>\n<h4>4. Thunk&#8217;lar\u0131 Test Etme<\/h4>\n<p>Thunk&#8217;lar\u0131 test etmek, i\u00e7erdikleri asenkron mant\u0131k nedeniyle normal eylem yarat\u0131c\u0131lar\u0131ndan biraz daha karma\u015f\u0131k olabilir. Ancak, <code>dispatch<\/code> ve API \u00e7a\u011fr\u0131lar\u0131n\u0131 mock&#8217;layarak kolayca test edilebilirler.<\/p>\n<pre><code class=\"language-javascript\">\/\/ userActions.test.js\nimport { fetchUsers, fetchUsersRequest, fetchUsersSuccess, fetchUsersFailure } from '.\/userActions';\nimport axios from 'axios';\nimport MockAdapter from 'axios-mock-adapter'; \/\/ axios isteklerini mocklamak i\u00e7in\n\ndescribe('fetchUsers thunk', () => {\n  let store;\n  let mock;\n\n  beforeEach(() => {\n    \/\/ store'u mock'la, sadece dispatch fonksiyonu \u00f6nemlidir\n    store = {\n      dispatch: jest.fn(), \/\/ dispatch'i bir mock fonksiyonu yap\n      getState: jest.fn(), \/\/ getState'i de mock'layabiliriz\n    };\n    mock = new MockAdapter(axios); \/\/ axios'u mock'la\n  });\n\n  afterEach(() => {\n    mock.restore(); \/\/ Her testten sonra mock'u s\u0131f\u0131rla\n  });\n\n  it('ba\u015far\u0131l\u0131 bir API \u00e7a\u011fr\u0131s\u0131 durumunda do\u011fru eylemleri dispatch etmeli', async () => {\n    const users = [{ id: 1, name: 'Test User' }];\n    mock.onGet('https:\/\/jsonplaceholder.typicode.com\/users').reply(200, users);\n\n    await fetchUsers()(store.dispatch, store.getState); \/\/ Thunk'\u0131 \u00e7a\u011f\u0131r\n\n    expect(store.dispatch).toHaveBeenCalledTimes(2); \/\/ REQUEST ve SUCCESS olmak \u00fczere 2 kez dispatch edilmeli\n    expect(store.dispatch).toHaveBeenNthCalledWith(1, fetchUsersRequest());\n    expect(store.dispatch).toHaveBeenNthCalledWith(2, fetchUsersSuccess(users));\n  });\n\n  it('ba\u015far\u0131s\u0131z bir API \u00e7a\u011fr\u0131s\u0131 durumunda hata eylemini dispatch etmeli', async () => {\n    const errorMessage = 'Network Error';\n    mock.onGet('https:\/\/jsonplaceholder.typicode.com\/users').networkErrorOnce();\n\n    await fetchUsers()(store.dispatch, store.getState);\n\n    expect(store.dispatch).toHaveBeenCalledTimes(2);\n    expect(store.dispatch).toHaveBeenNthCalledWith(1, fetchUsersRequest());\n    expect(store.dispatch).toHaveBeenNthCalledWith(2, fetchUsersFailure(errorMessage));\n  });\n});<\/code><\/pre>\n<p>Bu testler, thunk&#8217;\u0131n beklenen eylemleri do\u011fru zamanlarda ve do\u011fru verilerle <code>dispatch<\/code> etti\u011finden emin olman\u0131z\u0131 sa\u011flar.<\/p>\n<h3>Redux Thunk Alternatifleri (K\u0131sa Bir Bak\u0131\u015f)<\/h3>\n<p>Redux ekosisteminde asenkron i\u015flemleri y\u00f6netmek i\u00e7in Redux Thunk&#8217;tan ba\u015fka g\u00fc\u00e7l\u00fc middleware&#8217;ler de bulunmaktad\u0131r. En pop\u00fcler alternatifler Redux Saga ve Redux Observable&#8217;d\u0131r.<\/p>\n<p>*   <strong>Redux Saga<\/strong>: Generator fonksiyonlar\u0131n\u0131 (ES6) kullanarak yan etkileri y\u00f6neten bir middleware&#8217;dir. Saga&#8217;lar, daha bildirimsel bir yakla\u015f\u0131mla karma\u015f\u0131k asenkron i\u015f ak\u0131\u015flar\u0131n\u0131 tan\u0131mlaman\u0131za olanak tan\u0131r. \u0130\u015flemleri iptal etme, e\u015fzamanl\u0131l\u0131k kontrol\u00fc ve daha karma\u015f\u0131k durumlar i\u00e7in g\u00fc\u00e7l\u00fc ara\u00e7lar sunar. \u00d6\u011frenme e\u011frisi Thunk&#8217;a g\u00f6re daha diktir, ancak b\u00fcy\u00fck ve karma\u015f\u0131k uygulamalarda daha iyi bir yap\u0131land\u0131rma ve test edilebilirlik sa\u011flayabilir.<\/p>\n<p>*   <strong>Redux Observable<\/strong>: RxJS (Reactive Extensions for JavaScript) k\u00fct\u00fcphanesini temel alan bir middleware&#8217;dir. Ak\u0131\u015f tabanl\u0131 (stream-based) bir yakla\u015f\u0131mla asenkron i\u015flemleri ve yan etkileri y\u00f6netir. RxJS&#8217;in g\u00fc\u00e7l\u00fc operat\u00f6rleri sayesinde, olaylar\u0131n zaman i\u00e7indeki ak\u0131\u015f\u0131n\u0131 manip\u00fcle etmek ve d\u00f6n\u00fc\u015ft\u00fcrmek i\u00e7in \u00e7ok esnek bir yol sunar. Reaktif programlamaya a\u015fina olanlar i\u00e7in g\u00fc\u00e7l\u00fc bir ara\u00e7t\u0131r, ancak RxJS&#8217;in \u00f6\u011frenilmesi de ayr\u0131 bir \u00e7aba gerektirir.<\/p>\n<p><strong>Neden Redux Thunk Hala Pop\u00fcler?<\/strong><\/p>\n<p>Redux Thunk, basitli\u011fi, hafifli\u011fi ve do\u011frudan JavaScript&#8217;in yerle\u015fik asenkron \u00f6zelliklerini (Promise&#8217;ler, <code>async\/await<\/code>) kullanmas\u0131 nedeniyle bir\u00e7ok proje i\u00e7in tercih edilen se\u00e7enektir. K\u00fc\u00e7\u00fck ve orta \u00f6l\u00e7ekli uygulamalar i\u00e7in genellikle fazlas\u0131yla yeterlidir. Ek bir k\u00fct\u00fcphane veya paradigma (generator&#8217;lar, reaktif programlama) \u00f6\u011frenme ihtiyac\u0131n\u0131 ortadan kald\u0131r\u0131r, bu da yeni ba\u015flayanlar veya daha az karma\u015f\u0131k asenkron ihtiya\u00e7lar\u0131 olan projeler i\u00e7in idealdir.<\/p>\n<h3>Redux Thunk&#8217;\u0131n Art\u0131lar\u0131 ve Eksileri<\/h3>\n<p>Her ara\u00e7 gibi, Redux Thunk&#8217;\u0131n da kendi avantajlar\u0131 ve dezavantajlar\u0131 vard\u0131r.<\/p>\n<h4>Art\u0131lar\u0131:<\/h4>\n<p>1.  <strong>Basit ve Hafif<\/strong>: Redux Thunk&#8217;\u0131n kod taban\u0131 olduk\u00e7a k\u00fc\u00e7\u00fckt\u00fcr ve kavramsal olarak anla\u015f\u0131lmas\u0131 kolayd\u0131r. Redux&#8217;a yeni ba\u015flayanlar i\u00e7in ideal bir ba\u015flang\u0131\u00e7 noktas\u0131d\u0131r.<br \/>\n2.  <strong>D\u00fc\u015f\u00fck \u00d6\u011frenme E\u011frisi<\/strong>: JavaScript&#8217;in mevcut asenkron yap\u0131lar\u0131n\u0131 (Promise&#8217;ler, <code>async\/await<\/code>) do\u011frudan kullan\u0131r. Ek bir paradigma veya \u00f6zel bir syntax \u00f6\u011frenmenize gerek kalmaz.<br \/>\n3.  <strong>Do\u011frudan <code>dispatch<\/code> ve <code>getState<\/code> Eri\u015fimi<\/strong>: Thunk fonksiyonu i\u00e7inde store&#8217;un <code>dispatch<\/code> ve <code>getState<\/code> metotlar\u0131na do\u011frudan eri\u015fim, b\u00fcy\u00fck esneklik sa\u011flar.<br \/>\n4.  <strong>Esneklik<\/strong>: Asenkron i\u015flemleri, ko\u015fullu mant\u0131\u011f\u0131 ve birden fazla eylem <code>dispatch<\/code> etmeyi kolayca y\u00f6netebilir.<br \/>\n5.  <strong>Yayg\u0131n Kullan\u0131m<\/strong>: Redux Toolkit taraf\u0131ndan varsay\u0131lan olarak dahil edilmesi ve geni\u015f topluluk deste\u011fi sayesinde yayg\u0131n olarak kullan\u0131l\u0131r.<\/p>\n<h4>Eksileri:<\/h4>\n<p>1.  <strong>Karma\u015f\u0131k Mant\u0131k Birikimi<\/strong>: \u00c7ok karma\u015f\u0131k asenkron ak\u0131\u015flar veya birden fazla ba\u011f\u0131ml\u0131 API \u00e7a\u011fr\u0131s\u0131 i\u00e7eren senaryolarda, thunk fonksiyonlar\u0131n\u0131n i\u00e7inde \u00e7ok fazla mant\u0131k birikebilir. Bu, thunk&#8217;lar\u0131n okunabilirli\u011fini ve bak\u0131m\u0131n\u0131 zorla\u015ft\u0131rabilir (&#8220;callback hell&#8221; benzeri bir durum).<br \/>\n2.  <strong>\u0130\u015flem \u0130ptali Zorlu\u011fu<\/strong>: Devam eden bir asenkron i\u015flemi (\u00f6rne\u011fin bir API \u00e7a\u011fr\u0131s\u0131) iptal etmek, Thunk ile do\u011frudan desteklenmez ve manuel olarak y\u00f6netilmesi gerekir. Redux Saga veya Redux Observable gibi alternatifler, bu t\u00fcr senaryolar i\u00e7in daha g\u00fc\u00e7l\u00fc yerle\u015fik mekanizmalara sahiptir.<br \/>\n3.  <strong>Test Edilebilirlik (Bazen Daha Zor)<\/strong>: Thunk&#8217;lar genellikle yan etkiler i\u00e7erdi\u011fi i\u00e7in, test yazarken API \u00e7a\u011fr\u0131lar\u0131n\u0131 ve <code>dispatch<\/code> fonksiyonunu mock&#8217;lamak gerekir. Bu, baz\u0131 durumlarda Redux Saga&#8217;n\u0131n daha bildirimsel test yakla\u015f\u0131mlar\u0131na g\u00f6re biraz daha zorlay\u0131c\u0131 olabilir.<br \/>\n4.  <strong>Geli\u015fmi\u015f \u00d6zellik Eksikli\u011fi<\/strong>: E\u015fzamanl\u0131l\u0131k kontrol\u00fc, debouncing\/throttling gibi geli\u015fmi\u015f yan etki y\u00f6netimi desenleri i\u00e7in Thunk&#8217;\u0131n \u00fczerine manuel olarak kod yazmak gerekir.<\/p>\n<h3>Sonu\u00e7<\/h3>\n<p>Redux Thunk, Redux uygulamalar\u0131nda asenkron i\u015flemleri y\u00f6netmek i\u00e7in vazge\u00e7ilmez bir ara\u00e7t\u0131r. Redux&#8217;\u0131n indirgeyicilerin safl\u0131\u011f\u0131 ve eylemlerin d\u00fcz nesneler olmas\u0131 gibi temel prensipleriyle asenkronlu\u011fun do\u011fas\u0131ndaki yan etkiler aras\u0131ndaki bo\u015flu\u011fu doldurur. Eylem yarat\u0131c\u0131lar\u0131n\u0131n d\u00fcz nesneler yerine fonksiyonlar d\u00f6nd\u00fcrmesine izin vererek, bu fonksiyonlar\u0131n i\u00e7inde API \u00e7a\u011fr\u0131lar\u0131 yapma, birden fazla eylem <code>dispatch<\/code> etme ve mevcut Redux durumuna eri\u015ferek ko\u015fullu mant\u0131k y\u00fcr\u00fctme yetene\u011fi sa\u011flar.<\/p>\n<p>Kurulumu ve kullan\u0131m\u0131 kolay olmas\u0131, d\u00fc\u015f\u00fck \u00f6\u011frenme e\u011frisi sunmas\u0131 ve JavaScript&#8217;in yerle\u015fik asenkron mekanizmalar\u0131n\u0131 kullanmas\u0131 nedeniyle Redux Thunk, \u00f6zellikle k\u00fc\u00e7\u00fck ve orta \u00f6l\u00e7ekli projeler i\u00e7in pop\u00fcler bir tercih olmaya devam etmektedir. Redux Toolkit&#8217;in varsay\u0131lan olarak Thunk&#8217;\u0131 i\u00e7ermesi, onun Redux ekosistemindeki merkezi rol\u00fcn\u00fc daha da peki\u015ftirmektedir.<\/p>\n<p>Ancak, \u00e7ok karma\u015f\u0131k asenkron i\u015f ak\u0131\u015flar\u0131, iptal edilebilir i\u015flemler veya y\u00fcksek d\u00fczeyde e\u015fzamanl\u0131l\u0131k gerektiren durumlarla kar\u015f\u0131la\u015f\u0131ld\u0131\u011f\u0131nda, Redux Saga veya Redux Observable gibi daha g\u00fc\u00e7l\u00fc ve bildirimsel alternatifler de\u011ferlendirilebilir. Yine de, \u00e7o\u011fu Redux uygulamas\u0131 i\u00e7in Redux Thunk, asenkron eylemleri temiz, \u00f6ng\u00f6r\u00fclebilir ve y\u00f6netilebilir bir \u015fekilde ele almak i\u00e7in yeterli ve etkili bir \u00e7\u00f6z\u00fcmd\u00fcr. Redux Thunk&#8217;\u0131 anlamak ve ustaca kullanmak, modern Redux tabanl\u0131 uygulamalar geli\u015ftiren her geli\u015ftirici i\u00e7in temel bir beceridir.<\/body><\/p>\n","protected":false},"excerpt":{"rendered":"Redux Thunk ile Asenkron Redux Eylemlerini Anlamak\nGiri\u015f: Redux ve Asenkronlu\u011fun Zorunlulu\u011fu\nModern web uygulamalar\u0131, kullan\u0131c\u0131 deneyimini zen","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"csco_page_header_type":"","csco_page_load_nextpost":"","csco_page_subscribe_form":"","csco_page_contact_form":"","footnotes":""},"categories":[1],"tags":[],"class_list":{"0":"post-34704","1":"post","2":"type-post","3":"status-publish","4":"format-standard","6":"category-genel","7":"cs-entry","8":"cs-video-wrap"},"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v20.5 (Yoast SEO v25.3.1) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Redux Thunk ile Asenkron Redux Eylemlerini Anlamak - Kodlar\u0131n Gizemli D\u00fcnyas\u0131<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/fatihsoysal.com\/blog\/redux-thunk-ile-asenkron-redux-eylemlerini-anlamak\/\" \/>\n<meta property=\"og:locale\" content=\"tr_TR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Redux Thunk ile Asenkron Redux Eylemlerini Anlamak\" \/>\n<meta property=\"og:description\" content=\"Redux Thunk ile Asenkron Redux Eylemlerini Anlamak Giri\u015f: Redux ve Asenkronlu\u011fun Zorunlulu\u011fu Modern web uygulamalar\u0131, kullan\u0131c\u0131 deneyimini zen\" \/>\n<meta property=\"og:url\" content=\"https:\/\/fatihsoysal.com\/blog\/redux-thunk-ile-asenkron-redux-eylemlerini-anlamak\/\" \/>\n<meta property=\"og:site_name\" content=\"Kodlar\u0131n Gizemli D\u00fcnyas\u0131\" \/>\n<meta property=\"article:published_time\" content=\"2025-11-20T22:40:58+00:00\" \/>\n<meta name=\"author\" content=\"Fatih Soysal\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Yazan:\" \/>\n\t<meta name=\"twitter:data1\" content=\"Fatih Soysal\" \/>\n\t<meta name=\"twitter:label2\" content=\"Tahmini okuma s\u00fcresi\" \/>\n\t<meta name=\"twitter:data2\" content=\"21 dakika\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/redux-thunk-ile-asenkron-redux-eylemlerini-anlamak\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/redux-thunk-ile-asenkron-redux-eylemlerini-anlamak\/\"},\"author\":{\"name\":\"Fatih Soysal\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\"},\"headline\":\"Redux Thunk ile Asenkron Redux Eylemlerini Anlamak\",\"datePublished\":\"2025-11-20T22:40:58+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/redux-thunk-ile-asenkron-redux-eylemlerini-anlamak\/\"},\"wordCount\":3423,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\"},\"inLanguage\":\"tr\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/fatihsoysal.com\/blog\/redux-thunk-ile-asenkron-redux-eylemlerini-anlamak\/#respond\"]}],\"copyrightYear\":\"2025\",\"copyrightHolder\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/redux-thunk-ile-asenkron-redux-eylemlerini-anlamak\/\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/redux-thunk-ile-asenkron-redux-eylemlerini-anlamak\/\",\"name\":\"Redux Thunk ile Asenkron Redux Eylemlerini Anlamak - Kodlar\u0131n Gizemli D\u00fcnyas\u0131\",\"isPartOf\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#website\"},\"datePublished\":\"2025-11-20T22:40:58+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/redux-thunk-ile-asenkron-redux-eylemlerini-anlamak\/#breadcrumb\"},\"inLanguage\":\"tr\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/fatihsoysal.com\/blog\/redux-thunk-ile-asenkron-redux-eylemlerini-anlamak\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/redux-thunk-ile-asenkron-redux-eylemlerini-anlamak\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Anasayfa\",\"item\":\"https:\/\/fatihsoysal.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Redux Thunk ile Asenkron Redux Eylemlerini Anlamak\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#website\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/\",\"name\":\"Fatihsoysal.com\",\"description\":\"Blog - Yaz\u0131l\u0131m D\u00fcnyas\u0131 Tecr\u00fcbelerim\",\"publisher\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/fatihsoysal.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"tr\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\",\"name\":\"Fatih Soysal\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"tr\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png\",\"contentUrl\":\"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png\",\"width\":512,\"height\":512,\"caption\":\"Fatih Soysal\"},\"logo\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/\"},\"description\":\"Kullan\u0131m ve kodlama m\u00fckemmeliyetini odak alan uygulamalar olu\u015fturma deneyimine sahip, profesyonel olarak 15+ y\u0131l \u00fczeri deneyime sahip bir yaz\u0131l\u0131m m\u00fchendisi.\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/author\/fatihsoysal\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Redux Thunk ile Asenkron Redux Eylemlerini Anlamak - Kodlar\u0131n Gizemli D\u00fcnyas\u0131","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/fatihsoysal.com\/blog\/redux-thunk-ile-asenkron-redux-eylemlerini-anlamak\/","og_locale":"tr_TR","og_type":"article","og_title":"Redux Thunk ile Asenkron Redux Eylemlerini Anlamak","og_description":"Redux Thunk ile Asenkron Redux Eylemlerini Anlamak Giri\u015f: Redux ve Asenkronlu\u011fun Zorunlulu\u011fu Modern web uygulamalar\u0131, kullan\u0131c\u0131 deneyimini zen","og_url":"https:\/\/fatihsoysal.com\/blog\/redux-thunk-ile-asenkron-redux-eylemlerini-anlamak\/","og_site_name":"Kodlar\u0131n Gizemli D\u00fcnyas\u0131","article_published_time":"2025-11-20T22:40:58+00:00","author":"Fatih Soysal","twitter_card":"summary_large_image","twitter_misc":{"Yazan:":"Fatih Soysal","Tahmini okuma s\u00fcresi":"21 dakika"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/fatihsoysal.com\/blog\/redux-thunk-ile-asenkron-redux-eylemlerini-anlamak\/#article","isPartOf":{"@id":"https:\/\/fatihsoysal.com\/blog\/redux-thunk-ile-asenkron-redux-eylemlerini-anlamak\/"},"author":{"name":"Fatih Soysal","@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1"},"headline":"Redux Thunk ile Asenkron Redux Eylemlerini Anlamak","datePublished":"2025-11-20T22:40:58+00:00","mainEntityOfPage":{"@id":"https:\/\/fatihsoysal.com\/blog\/redux-thunk-ile-asenkron-redux-eylemlerini-anlamak\/"},"wordCount":3423,"commentCount":0,"publisher":{"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1"},"inLanguage":"tr","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/fatihsoysal.com\/blog\/redux-thunk-ile-asenkron-redux-eylemlerini-anlamak\/#respond"]}],"copyrightYear":"2025","copyrightHolder":{"@id":"https:\/\/fatihsoysal.com\/blog\/#organization"}},{"@type":"WebPage","@id":"https:\/\/fatihsoysal.com\/blog\/redux-thunk-ile-asenkron-redux-eylemlerini-anlamak\/","url":"https:\/\/fatihsoysal.com\/blog\/redux-thunk-ile-asenkron-redux-eylemlerini-anlamak\/","name":"Redux Thunk ile Asenkron Redux Eylemlerini Anlamak - Kodlar\u0131n Gizemli D\u00fcnyas\u0131","isPartOf":{"@id":"https:\/\/fatihsoysal.com\/blog\/#website"},"datePublished":"2025-11-20T22:40:58+00:00","breadcrumb":{"@id":"https:\/\/fatihsoysal.com\/blog\/redux-thunk-ile-asenkron-redux-eylemlerini-anlamak\/#breadcrumb"},"inLanguage":"tr","potentialAction":[{"@type":"ReadAction","target":["https:\/\/fatihsoysal.com\/blog\/redux-thunk-ile-asenkron-redux-eylemlerini-anlamak\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/fatihsoysal.com\/blog\/redux-thunk-ile-asenkron-redux-eylemlerini-anlamak\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Anasayfa","item":"https:\/\/fatihsoysal.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Redux Thunk ile Asenkron Redux Eylemlerini Anlamak"}]},{"@type":"WebSite","@id":"https:\/\/fatihsoysal.com\/blog\/#website","url":"https:\/\/fatihsoysal.com\/blog\/","name":"Fatihsoysal.com","description":"Blog - Yaz\u0131l\u0131m D\u00fcnyas\u0131 Tecr\u00fcbelerim","publisher":{"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/fatihsoysal.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"tr"},{"@type":["Person","Organization"],"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1","name":"Fatih Soysal","image":{"@type":"ImageObject","inLanguage":"tr","@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/","url":"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png","contentUrl":"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png","width":512,"height":512,"caption":"Fatih Soysal"},"logo":{"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/"},"description":"Kullan\u0131m ve kodlama m\u00fckemmeliyetini odak alan uygulamalar olu\u015fturma deneyimine sahip, profesyonel olarak 15+ y\u0131l \u00fczeri deneyime sahip bir yaz\u0131l\u0131m m\u00fchendisi.","url":"https:\/\/fatihsoysal.com\/blog\/author\/fatihsoysal\/"}]}},"yoast_meta":{"yoast_wpseo_title":"","yoast_wpseo_metadesc":"","yoast_wpseo_canonical":""},"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts\/34704","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/comments?post=34704"}],"version-history":[{"count":1,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts\/34704\/revisions"}],"predecessor-version":[{"id":34705,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts\/34704\/revisions\/34705"}],"wp:attachment":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/media?parent=34704"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/categories?post=34704"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/tags?post=34704"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}