{"id":7639,"date":"2019-11-17T18:23:19","date_gmt":"2019-11-17T18:23:19","guid":{"rendered":"http:\/\/putridparrot.com\/blog\/?p=7639"},"modified":"2019-11-17T18:23:19","modified_gmt":"2019-11-17T18:23:19","slug":"redux-saga","status":"publish","type":"post","link":"https:\/\/putridparrot.com\/blog\/redux-saga\/","title":{"rendered":"Redux saga"},"content":{"rendered":"<p>Redux sagas allow us to handle application side effects, such as asynchronous loading of data.<\/p>\n<p>Assuming you have a React application created, we need run the following<\/p>\n<ul>\n<li>yarn add react-redux<\/li>\n<li>yarn add redux-saga<\/li>\n<\/ul>\n<p>To create a simple demo, we&#8217;ll change the App.js file to <\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\nimport React from 'react';\r\nimport store from '.\/store';\r\nimport { Fetch } from '.\/rootReducer';\r\n\r\nfunction App() {\r\n\r\n  function handleDoFetch() {\r\n    store.dispatch({type: Fetch});\r\n  }\r\n\r\n  return (\r\n    &lt;div className=&quot;App&quot;&gt;\r\n      &lt;button onClick={handleDoFetch}&gt;Do Fetch&lt;\/button&gt;\r\n    &lt;\/div&gt;\r\n  );\r\n}\r\n\r\nexport default App;\r\n<\/pre>\n<p>So this will simply dispatch an action which will ultimately be handled by our saga. Before this happens let&#8217;s create a redux store and set up the redux saga middleware, here&#8217;s my store.js file<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\nimport { createStore, applyMiddleware, combineReducers } from &quot;redux&quot;;\r\nimport createSagaMiddleware from &quot;redux-saga&quot;;\r\nimport rootReducer from &quot;.\/rootReducer&quot;;\r\nimport rootSaga from &quot;.\/rootSaga&quot;;\r\n\r\nexport const sagaMiddleware = createSagaMiddleware();\r\n\r\nconst store = applyMiddleware(sagaMiddleware)(createStore)(\r\n  combineReducers({\r\n    rootReducer,\r\n  })\r\n);\r\n\r\nsagaMiddleware.run(rootSaga);\r\n\r\nexport default store;\r\n<\/pre>\n<p>We don&#8217;t need to combineReducers as there&#8217;s only one, but it&#8217;s there for an example of setting up multiple reducers. Let&#8217;s now create a very basic reducer named rootReducer.js<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\nexport const Fetch = &quot;FETCH&quot;;\r\nexport const FetchEnded = &quot;FETCH_ENDED&quot;;\r\n\r\nexport default (state = {}, action) =&gt; {\r\n  switch (action.type) {\r\n    case FetchEnded:\r\n      console.log(&quot;Fetch Ended&quot;);\r\n      return {\r\n        ...state,\r\n        data: &quot;Fetch Ended&quot;\r\n      }\r\n    default:\r\n      break;\r\n  }   \r\n  return state;\r\n}\r\n<\/pre>\n<p>Notice we&#8217;ve got two actions exported, <em>Fetch<\/em> and <em>FetchEnded<\/em> but there&#8217;s nothing handling <em>Fetch<\/em> in this case. This is because redux middleware will pass this through to the redux-saga we&#8217;re about to create. We could also handle <em>Fetch<\/em> here and still handle it also within the saga, the point being the saga is going to handle this action when it see&#8217;s it.<\/p>\n<p>Now we&#8217;ve got everything in place, let&#8217;s put the final piece in place, the saga will be stored in rootSaga.js and here it is<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\nimport { put, takeLatest } from 'redux-saga\/effects'\r\nimport { Fetch, FetchEnded } from &quot;.\/rootReducer&quot;;\r\n\r\nfunction *fetchData() {\r\n    console.log(&quot;fetchData&quot;)\r\n    yield put({ type: FetchEnded });\r\n}\r\n\r\nfunction* rootSaga() {\r\n    yield takeLatest(Fetch, fetchData);\r\n}\r\n\r\nexport default rootSaga;\r\n<\/pre>\n<p>Notice that the <em>rootSaga<\/em> function is a function generator and it yields the result of a call to <em>fetchData<\/em> each time the <em>Fetch<\/em> action is detected.<\/p>\n<p>It might be the <em>fetchData<\/em> yield&#8217;s many values or even sits in a loop yielding data but in this example we&#8217;ve kept things simple. Running the application will display a button and using the browser&#8217;s dev tools, when the button is pressed the <em>Fetch<\/em> action is detected by the saga and the <em>fetchData<\/em> function runs, which then in turn dispatches a <em>FetchEnded<\/em> action which is handled by the reducer.<\/p>\n<p>As stated, our <em>fetchData<\/em> is very simple but in a real world scenario this function could be acting as a websocket client and for every value returned would yield each value within a while(true) loop or the likes until cancelled or maybe an error ocurred.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Redux sagas allow us to handle application side effects, such as asynchronous loading of data. Assuming you have a React application created, we need run the following yarn add react-redux yarn add redux-saga To create a simple demo, we&#8217;ll change the App.js file to import React from &#8216;react&#8217;; import store from &#8216;.\/store&#8217;; import { Fetch [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[45,274],"tags":[],"class_list":["post-7639","post","type-post","status-publish","format-standard","hentry","category-javascript","category-redux-saga"],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/7639","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/comments?post=7639"}],"version-history":[{"count":4,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/7639\/revisions"}],"predecessor-version":[{"id":7698,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/7639\/revisions\/7698"}],"wp:attachment":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/media?parent=7639"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/categories?post=7639"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/tags?post=7639"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}