RSS Amplifier

James' Blog · Jun 7, 2017

Using async and await with React and Redux

0
Sign in to vote or save

jamesbaum.co.uk

I've been playing around with using async and await in my Redux reducers to get rid of all the Promise callback functions - this stuff's like magic!

Note: I'm using Webpack and compiling with the babel-preset-stage-0 for ES2016 await/async.

Before

This is my login function using a Promise and fetch to send data to the API:

export const login = (username, password) => {
  // using thunk middleware since it's async, so return a function
  return (dispatch) => {
    // create data to send via fetch
    const data = new FormData();
    data.append("username", username);
    data.append("password", password);

    // fire the request
    fetch("http://localhost/login", {
      method: "POST",
      body: data,
    })
      // wait for data back
      .then((response) => response.json())

      // response.json() is also async, so wait for that to finish
      .then((data) => dispatch(loginSuccess(data)))

      // catch any errors
      .catch((err) => dispatch(loginFailure(err)));
  };
};

After

Here's the function now I'm using async/await: I've split it into two functions so the async login request isn't nested. There's also no callback then() functions!

// this just wraps fetch - a simpler 'GET' could just be inline
// note the 'async' keyword
async function loginRequest(username, password) {
  const data = new FormData();
  data.append("username", username);
  data.append("password", password);

  // 'await' the response from fetch - no callback, you can just carry on
  // and use 'response' as normal rather than wrap it in a function!
  const response = await fetch("http://localhost/login", {
    method: "POST",
    body: data,
  });

  // response.json() is async too, but you don't need an 'await'
  // keyword in a return from 'async' (it's implied)
  return response.json();
}

// this is the reducer - no 'async' on the outer function since it just returns a function
export const login = (username, password) => {
  // this one's 'async'
  return async (dispatch) => {
    // wrap in try to listen for Promise rejections - equivalent of '.catch()'
    try {
      // wait for the fetch to finish then dispatch the result
      const data = await loginRequest(username, password);
      dispatch(loginSuccess(data));
    } catch (e) {
      // catch errors from fetch
      dispatch(loginFailure(e));
    }
  };
};

Read the original on jamesbaum.co.uk

Comments

Nothing yet. Say the first thing.

    Sign in to join the conversation.