DEV Community

Kevin Le
Kevin Le

Posted on

Modernize your ReactJS application with async/await in 2018

To start 2018, you can modernize your ReactJS application by incorporating the async/await feature. Assume you already use a Promise-based HTTP client library such as axios, you can easily refactor your existing code, or you can just start using async/await in new codes.

Either way or both, here's a small snippet that can help:

import axios from 'axios';
...
class Login extends Component {
    constructor(props, context) {
        super(props, context);
        this.onLogin = this.onLogin.bind(this);
        ...
    }
    async onLogin() {
        const { email, password } = this.state;
        try {
            const response = await axios.post('/login', { email, password });
            console.log(response);
        } catch (err) {
            //handle error
        }
    }
    ...
}

So the code change is very minimal. But running webpack might result in an error. The error might say something like regeneratorRuntime is not defined. In that case, it's a simple fix:

npm install babel-plugin-transform-runtime --save-dev

Then in the .babelrc file, simply add

{
    ...
    "plugins": [
        ["transform-runtime", {
            "regenerator": true
        }]
    ]
}

Other than adding babel-plugin-transform-runtime and a simple modification to the .babelrc file, no babel-runtime, no polyfill is necessary.

Top comments (4)

Collapse
 
domysee profile image
Dominik Weber

Did you have a look at the transpiled JS code?

While async/await is a great feature, the size of the transpiled code is enormous.

The simple onLogin method of your example gets transpiled to this:

var onLogin = function () {
    var _ref = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee() {
        var _state, email, password, response;

        return regeneratorRuntime.wrap(function _callee$(_context) {
            while (1) {
                switch (_context.prev = _context.next) {
                    case 0:
                        _state = undefined.state, email = _state.email, password = _state.password;
                        _context.prev = 1;
                        _context.next = 4;
                        return axios.post('/login', { email: email, password: password });

                    case 4:
                        response = _context.sent;

                        console.log(response);
                        _context.next = 10;
                        break;

                    case 8:
                        _context.prev = 8;
                        _context.t0 = _context['catch'](1);

                    case 10:
                    case 'end':
                        return _context.stop();
                }
            }
        }, _callee, undefined, [[1, 8]]);
    }));

    return function onLogin() {
        return _ref.apply(this, arguments);
    };
}();

So before using async/await, one should ask if the increased code size is acceptable.

Collapse
 
codeprototype profile image
Kevin Le

It's good to have an eye on the transpiled code. For a simple case, it might seem like there's no gain of using async/await over using then clauses. But the benefits of using async/await will be more obvious when the business logic gets more complicated. Async/await code will be more readable than "then" clauses.

Now if you have to stop each time to compare the size of the transpiled code, then I recommend against that. I also recommend against coming up with a rule that says something like "Ok, less than 2 "then" clauses, then no async/await".
Business logic does change. So suddenly we have to make one more asynchronous call, then such rule is more trouble than it's worth.

Collapse
 
nickytonline profile image
Nick Taylor

It depends what browsers you're targeting. Assuming (and I hope) you use babel-preset-env, async/await will only be transpiled to ES5 for pretty much just IE11 and below. All the other browsers support await now.

If most of your market is IE <= 11 , then maybe perhaps it's not wise to use async/await. Honestly though so many things come in to play for bundle size, but obviously a smaller bundle size is usually a good thing.

Thread Thread
 
domysee profile image
Dominik Weber

This is great news! Since it's ES7 I assumed it won't be implemented by browsers yet.

Thanks for pointing out that it is.

Regarding the bundle size, I agree that many things affect that. But I don't think that bloating up async/await statements to 10x the original code size is negligible.