Working With React and Flux
React is a powerful UI library developed at Facebook that uses an innovative diff algorithm to efficiently re-render components when data changes. With React, we don’t interact with the DOM directly - instead, React uses the concept of a Virtual DOM, which is just an abstract, lightweight representation of the actual DOM. This virtual DOM can then be manipulated and then saved to the real DOM tree. A major advantage of React is that this is done in an efficient way through the diffing algorithm used under the hood. The algorithm calculates the minimum number of elements it needs to update, and then efficiently re-renders the component by only applying these changes to the actual DOM. Calculating the diff between two trees (or more specifically, the “edit distance” between two trees) is a O(n^3) problem, but React uses heuristics based on a few practical use-case assumptions to bring it down to O(n). For more on that, check out the Docs.
React also has a few other notable features that make it pretty useful:
- Declarative style: components and elements allow you to write your component’s render() function in a declarative way.
- Reusability and composability: React’s components naturaly lend themselves to be reusable if they are designed well (for example, ensuring each component has only a single responsibility), and are therefore easy to compose with other components to quickly build complex user interfaces.
Flux is a pattern that complements React and the idea of unidirectional data flow. Its used internally at Facebook and is commonly paired with React. Its componsed of four components: Actions, Dispatcher, Store, and Controller Views, which manage the flow of data through an application and define what picks it up along the way. There’s many implementations of Flux, and the one I’ve been using is Alt.js.
React + Flux Example
Let’s create a simple React component, along with actions and a store for it. The store will be responsible for listening for actions and updating the state of our component accordingly. We’ll subscribe our React component to the store so that it knows about changes in the store, and can update its own state accordingly. Also, we’ll define a few actions that fetch data and notify the store about whether the data fetch was successful or not. Let’s get started with these actions first, which are placed into a file called
Here, we’ve defined three actions, one of which requests data from our backend, and two of which notify our store about the request’s success or failure. Note that we haven’t yet handled these two actions - that’ll be done when we define our handlers in the store. The store will also bind our actions to their handlers - sort of like a mapping from an action to the action handler. We’ll revisit this when we define our
MyComponentStore class. The last line of the above code simply exports our actions so that they can be imported elsewhere.
Defining the Component Store
Now, we can move on to defining a store for our React component. The store will be responsible for handling the actions we’ve defined and updating the state accordingly, so that our component can listen for state changes. Let’s put this code into a file called
bindActions is an Alt function that binds actions to their action handlers, with a specific naming convention. As an example, an action with name
doAction will bind to
onDoAction or just
doAction (but not both). In this case, when our
getMyMembersSuccess action occurs, the code in the handler
onGetMyMembersSuccess will be executed and the members field of the state will be updated. With our actions and store defined, we’re ready to define our actual React component.
Creating the React Component
Our React component will fire off actions (such as, in our example, getting members from the backend) and listen to the store for state changes. When our component is initially rendered, it sets its initial state to the store’s state, and also subscribes a listener to the store to listen for changes so that its state can be updated accordingly (the
OnChange function in the code below). Additionally, we can remove our store listener when the component is unmounted. Here’s some basic boilerplate code that could be used to design this component:
And that’s it! Hopefully, this was a good example to introduce how React and the Flux pattern work together to achieve unidirectional data flow, and how firing and handling actions update our component’s store. This full-stack tutorial is an excellent resource for learning more about React, Flux, and using Node to develop a full-stack app.