If you're reading this you probably already know something about Redux, and how it works with React. Just in case you don't here's a quick recap of the steps. This can seem quite complex at first, but the pattern is simple and always the same - which is one of the advantages of using Redux.
ExampleWhen you create an action to be dispatched to Redux, that action object needs to be a plain object, and normally looks like this. { type:'SOMETHING_WONDERFUL', payload:magnificentPayload } An action might look like this. const acSomethingWonderful = (payload) => { return {type: "SOMETHING_WONDERFUL" , payload:payload}; } In your React component, you would dispatch that action creator. this.props.dispatch (acSomethingWonderful()); AsynchronicitySo far so good, but when you have to deal with asynchronous actions (such as fetching data from an API), things can get complicated, and you may be tempted to start messing with the pattern, but there's no need. In this example, the user has clicked the button to signout of my application, which has been authenticated using Firebase. However I can't dispatch an action saying he has signed out, because that hasn't actually happened yet. The state we're currently in is that we've asked Firebase to sign out, but it's not yet completed. This means that any React components which are being rendered based on someone being signed in now need to be updated, but not yet - not until the signout is completed, so this simple action creator will not work. This is wrong... const acSignout = (payload) => { return {type: "AUTH_SIGNOUT" , payload:payload}; } Dispatching multiple actionsTo make this right, multiple actions need to be dispatched. One to say that the signout process has started, and another when it has finished (or failed). Here's an improved version, wrapped in a function that will end up creating multiple actions. These snippets are taken from the Ephemeral Exchange management console. export function acSignout() { return acPromise ( cs.actions.AUTH_SIGNOUT, getCurrentUid(), () => firebase.signOut ); } and in the component that detected the signout request this.props.dispatch (acSignout()); The function to be executed (firebase.signOut), is passed to the wrapper function below, which turns it into a promise (if it's not already one).
/** * actionType_PENDING is returned from this * and later when the function is completed, actionType_FULFILLED or _REJECTED are dispatched * @param {string} actionType the base action type * @param {*} pendingPayload the payload to dispatch with the _PENDING action * @param {func} function the function to execute that should return a promise * @return {object} the action to be dispatched */ export function acPromise (actionType, pendingPayload, func) { // later on I'll make this middleware so i dont need to pass the dispatcher // for now I have it stored somewhere const dispatch= Process.store.dispatch; // first check the function is actually a promise // and convert it if it isnt const theAction = typeof func.then === 'function' ? func : function () { return new Promise (function (resolve, reject) { try { resolve(func()); } catch(err) { reject (err); } }); }; // now we execute the thing, but dispatch a fullfilled/rejected when done theAction() .then (function (result) { // the result of the original function dispatch({ type:actionType+"_FULFILLED", payload:result }); }) .catch (function (err) { dispatch({ type:actionType+"_REJECTED", payload:err }); }); // what we return is the pending action return { type:actionType+"_PENDING", payload:pendingPayload }; } Here's the Redux logger view of what happened following the dispatch. Redux-promise middlewareThere are a couple of middlewares available such as redux-promise that can help with this, but I decided to roll my own, mainly because I wanted to be able to pass a payload while in the PENDING state too, and couldn't figure out how to do that with those other solutions. This creates the same action variants (PENDING,FULFILLED,REJECTED) as redux-promise. For more like this, see React, redux, redis, material-UI and firebase. Why not join our forum, follow the blog or follow me on twitter to ensure you get updates when they are available. |
Services > Desktop Liberation - the definitive resource for Google Apps Script and Microsoft Office automation > React, redux, redis, material-UI and firebase >