Messages About Condolences

A short condolence message is a way to express your sorrow for someone who has lost something or someone. It can be hard to find the right words to express grief and pain, but it is important to try…

Smartphone

独家优惠奖金 100% 高达 1 BTC + 180 免费旋转




Implementing a Bulletin Board in React.js

The implementation of the board took a lot of premeditation. My backend JSON API was written in Ruby on Rails and I had to decide how I would structure my routes and controllers to appropriate the requests and send efficient, nested responses. On the frontend side, my two main tools were React Draggable and Redux. A harmonious flow between the Draggable components, the Redux store, and the API was necessary to achieve success with this project.

My first considerations were to do with the mechanics of how notes were to be saved on the board. I considered whether data about notes should be persisted in real-time, after user actions, or at a regular interval. With real-time, the requests would be made on every position change of a note. In terms of React Draggable’s built-in methods, the requests would be made using the onDrag method. These patch requests would only update the relevant axis. If a user was dragging a note along the Y axis, the Rails controller responsible for the patch requests would ignore the static number on the X axis. In order for a user on the same board to be able to see these real-time changes, a web socket would need to be setup to send and receive the updated position of the note. Each patch request would need to be broadcast to a Action Cable channel so that the note’s new position is immediately received by the other users viewing the board. Overall, the data flow would be as follows.

Outside of the data consumption that this would require, there are two main reasons why this approach was faulty. First, React Draggable’s onDrag method updated a note’s movement in terms of milliseconds. Sending that many patch requests and subsequently re-rendering the note component for User 2 would be a taxing procedure and would likely be too slow. When User 1 moves the note, the note is being optimistically rendered whereas User 2 is seeing a real-time representation of the note’s actual data footprint. Writing a component that allows User 1 to be able to render optimistically without receiving the data simultaneously would be a challenge as well. The second issue has to do with user experience. While User 2 is viewing the board, a voodoo moving note might not be a welcoming experience. This last reason, simple and straightforward as it is, combined with the large data consumption was the main push behind my decision not to implement a real-time bulletin board.

Another option was to make the patch requests at regular intervals. Considering that this wouldn’t be efficient because the requests would be impartial to user actions, I ruled this option out very quickly. For User 2, receiving the updates at a set interval would contribute to the user experience problem I encountered when I considered a real-time board. Every so often User 2's optimistically rendered board would shift with the most recent changes that User 1 had made. This would interrupt the natural flow for User 2 and so I ditched the idea of using an interval for sending and receiving requests and responses.

After deliberation, I decided that the most effective way to implement this was to allow each user their own optimistically rendered board for as long as they remained on the page without refresh. For User 1, pocketing these patch requests behind certain user actions was the most effective way to send the data to the database and make the collaborative bulletin board work. React Draggable’s built-in onStop method allowed me to send a patch request with the note’s updated position after a user had finished dragging a note. This seemed the most natural point to send data to the API. In addition to the note’s updated position, I decided that a request would be sent to the API every time a note was created, deleted, or its content edited with the relevant data.

From the perspective of User 2, however, this data would not be received after User 1 made these actions. Rather, I leaned on the importance of each user having their own optimistically rendered board during each session. From a user experience point of view, I wanted each period of time in between refreshes to be a branch in which the user could manipulate the latest version of the board to their liking without other user’s interference. Only when a user switches over to another board or refreshes the page is the other user’s changes integrated into their own.

The one drawback to this method is the way that competing requests are resolved. If two users move the same note, both updates are going to be persisted to the database. The update that was persisted last is the update that remains. This does not happen when a user adds a note. If two users add a note separately of each other, both notes will be present to both users on refresh. If a user deletes a note while another tries to update that same note, this will result in a deleted note on refresh and a patch request error for the user trying to update the note. While this is how the application currently works, I designed the components with a fix to this problem in mind. Going forward, I will have a note become locked as soon as a user begins editing it. If User 1 is changing the text on a note, then the locked note will be represented to User 2 with a colored border and a caption describing that User 1 is currently editing it.

This will introduce the need for a simple web socket to be setup to broadcast and subscribe to this data in order to represent it for each user. In the meantime, however, the bulletin board has been implemented without the use of web sockets, which has been reserved for the real-time chat on each board. I built the Action Cable channel and the chatroom component in such a way that the web socket can be repurposed to send and receive data about which notes are currently being edited.

Now that I’ve covered the overview of my thought process in approaching the data needs and user experience concerns of the bulletin board, I’ll delve into my implementation of it. Using React for this implementation was a great advantage as the component-based structure made it easier to realize.

There are three components involved in the bulletin board. The first is the bulletin container which is responsible for interacting with the Redux store, sending and receiving note data, and passing this data down as props to render the note components. The second component is the board component which has the sole responsibility of filtering the bulletin container’s note props and rendering the note components. While the board component seems superfluous, its role in receiving the data from the bulletin container and restructuring it so that the note component can render itself properly was invaluable. As an intermediary, it allowed me to compartmentalize the API response from the database in the bulletin container and the frontend necessities of rendering that data in the note component.

Each note components’ position is determined by the pixel position on the div’s css. When a new note is created, a randomly generated left and top pixel value is created within the bounds of the board. These bounds are determined by the board div’s css properties. I made this a fixed distance and so when a screen is resized, the board compensates by becoming scrollable. While I had considered having the board distance be fluid and resizable, the method of using percentages instead of pixels would have made it hard for users to view the same arrangement of each board. Using pixels made this process easier and the transformations that occur when a note is moved were straightforward and required only determining the difference in pixels. This data is then sent through the bulletin container and that note instance is updated in the PostgreSQL database accordingly.

Achieving a draggable bulletin board required that each note could only be dragged within a given bound. Creating this logic required that I made each note component’s draggable bounds equal to that component’s parent div. By having each component’s draggable range determined by its parent div rather than a fixed distance opened the door to making the bulletin components easily reusable. This feature is a driving factor behind my other implementation of the bulletin board feature in the application. I was able to repurpose the board and note components and set up another bulletin board on the user home page to showcase a user’s boards as sticky note representations.

The use case agnostic approach to the entire component structure made reusing it to visualize a user’s boards a simple procedure. There are only two significant changes in the implementation of this meta-visualization. The first is the container, which in this case is the profile container. The profile container interacts with the Redux store and API in a similar way as the bulletin container. The only significant difference is that the Profile Container is reading from the user’s board list and not the board display page’s data. Besides the swapped containers, the way in which the position of a user’s boards is stored is different since each user has the ability to visualize their own boards in whichever arrangement they prefer. For this reason, the positional data is stored on a join table for the board and users rather than the note model itself in the case of the board display page. Altogether the mechanics of the rendering from the container down to the note components are the same.

While I’m confident that the basic mechanics of the collaborative bulletin board hold against any interfering bugs, the final product is far from polished with all of the intricate considerations of a seamless user experience. Going forward, implementing a board that makes collaborating not only possible but essential to resource-sharing will require an implementation of some form of a web socket for the bulletin components. By flagging to users who else is currently working on a board, the collaborative nature of the board are emphasized and the chat can be used to discuss the resources and their arrangement. With the current component structure and the chatroom’s built-in web socket approach, implementing these additional features will be a task within reach of the current product.

Add a comment

Related posts:

Can the World Stop Genocide?

Squatting on a UN refugee agency mat, clutching her listless two-year-old, Setera Bibi tells her story. Last year, at 4am on August 25th, the 23-year-old was awoken by gunfire. Fifty soldiers were…

HTML and CSS Beginner Learning Resources

Part of my job these days is to teach the basics of HTML and CSS. I’m always looking out for resources that can help me explain concepts and help those interested to speed up and solidify their…

Indiana Joins Growing List of States with Bills to Legalize Sports Betting if SCOTUS Kills PASPA

The list of states that are considering the possibility of regulating sports betting in the near future continues to grow. Indiana became the latest to introduce legislation that would take effect if…