• How to avoid concurrency issues in React by Ast

    React proposes a simple declarative way to build an application's view. It's straightforward to write a hierarchy of stateless components or to change a state synchronously. The whole app works as an integration of two pure functions "state(event)" and "view(state)". The behavior is testable and predictable. But you can't make something complex without depending on an external data sources integration: side effects come into the stage. Beware, you're approaching the Dark Zone of functional programming now :) 

    A network is the most common side effect in any web application. If a component fetches data from a remote location, you can't predict the time it would take the particular request to finish, and the order of your queries execution, or even the success status of the job. For example, let's assume the following situation, which is not a rare thing on a slow connection:

    1. A Component mounts and makes a request A with A1 arguments to fetch the data from a server
    2. User goes to another page or tab, so the Component unmounts
    3. User goes back to the first page and the Component mounts again and makes a request B with B1 arguments to fetch the data
    4. Request B was very lucky, and it completes first
    5. Request A completes only after request B

    If you use external state storage, like Redux, your Component will receive old data. Even if you use a local state for a component, there would be an entirely useless waste of user's bandwidth (and highly probable -- a lot of warnings in a console!)

    Simple Component with an external data source

    Let's build a simple component to fetch an avatar URL from github.com for a given person. And let's make it as simple as it's possible while still keeping in mind all the loading and error handling stuff.

    Now, if you limit the network speed and try to ask it about different persons, you will see a lot of requests, and none of them would be canceled. Let's address this problem using a high order component implementing the cancellation logic.

    Component wrapped with Request Watcher

    The idea behind this HOC is to create a token and pass it into every function call with network side effects. The request watcher HOC will watch the React lifecycle for you. If Component cease to exist or there are more recent calls to that function, it will cancel the request. As a bonus, it will look if your props are changed to decide whether to run a new query or you'd be fine without it.

comments powered by Disqus