P2P WebRTC file sharing app: Frontend using React & Flux

React is one of the frontend framework that everyone is talking about these days. I wanted to see what all the fuss was about and also learn a modern JS framework in the process, hence I used React in building filecha.in (source code) which is a pretty simple peer to peer file sharing web app using WebRTC.

In this post I am going to go over some basic things I liked about React and how I architectured the frontend of filecha.in.

Composition

Composition is a cornerstone of building complex systems by combining smaller components. When I started using React, this is the first thing I loved, that it had composition as part of the framework. In this case it was composition of UI components to build more complex components.
A component in React is a renderable entity that takes some state information and renders it, they way I like to think of it is as custom HTML elements (similar to WebComponents).
Components can use other components in their rendering. An example of it would be that in a list of items, list is one component and an item in the list will be another component. So <ListComponent/> will be composed of an array of <ItemComponent/>.
This allows the developers to build more generic and cohesive component that they can easily reuse across their application.

JSX

We all have scars from PHP era, when HTML & PHP were part of the same code and there might be some SQL in the mix as well. This made things ugly very quickly, good that we now have frameworks that keeps separate things separate.
In case of React it goes back to keeping UI code and its logic in the same place, but it does it in a way which does not make it messy, but instead makes it more manageable.

The pro of doing this is that you don't have to navigate between the template code and the controller code to make changes, instead everything is at one place and the HTML (or JSX) is under one function primarily.
The JSX allows you to use javascript in your HTML code as well, but you should use it sparingly and only when it makes sense.

Flux

As I started building my app, I ran into the problem of how do I manage state in a clean way. Thats when I stumbled upon Flux. Flux is not a framework instead it's a way of architecting your React application where you have to maintain state and its business logic. Many frameworks have been developed that allow you to build your application using that architecture.

Components in Flux

In Flux we have the following components.

  1. Action: You can think of actions as an event with some data.
  2. Store: It is responsible for storing the state and maintaining any changes to it. It listens to various actions, so that it can update its state.
  3. Dispatcher: This is the middle component between Action & Store which decouples both of them. It is aware of that which action should go to which store. In this way we can change the store without changing any other part of the system.

One direction data flow

React & Flux data flow

If you have used other frameworks then you would have stumbled upon data binding which allows you to keep the Model and the View state in sync.
React does not follow the same concept of data binding. React has a more simpler approach i.e. one way flow. The flow works as the diagram suggests, that any change in view or user action will send an action to store (using dispatcher), store will change its state and send it to view which updates its state and re-renders.

You might think that this couples the Store & View. The way to decouple it is that the store can also emit events when it has made changes to data, the view registers to listen for that events. Only the bigger component should listen to such events and pass the necessary data to its children components, in this way not all views are coupled with that event, only few big ones are.

Compnent event registration

Filecha.in frontend architecture

Following is the frontend architecture of Filecha.in.
Filecha.in achitecutre Flux + React

I have the following two stores

  1. FileInfoStore: This store is responsible for managing the files dragged & dropped by the user. It listens to actions to create, delete file etc.
  2. FileTransferManager This store is responsible for having the logic to either start downloading the file that the user clicks and also uploading the file. This manages the states of various transfer going on such as the progress etc.

I have the following React components

  1. FileShareApp: This is uber component that manages other components, listens for events from both the FileInfoStore & FileTransferManager. It also dispatches action to create & download files.
  2. FileHandler: This component is responsible for handling drag and drop of files. When the user drags a file on it, it callback a function in FileShareApp which dispatches the action to create the file.
  3. PeerConnectionStatus: This shows information regarding the peer id and whether it is connected with other peer or not.
  4. ItemsList: This maintains the list of items i.e. files in this case.
  5. ListItem: It is the card for a particular file and handles actions associated to it from the user e.g. download file, delete file etc.

You can see the source code here.
Let me know in comments if you have any suggestion to make it more manageable or any other ideas.

Resources: