Being recently laid off I took the chance to upskill. With a solid background in backend development I decided to learn how to build a frontend, namely with HTML, JavaScript, and React.
Every developer comes across the term "functional programming" at least once in their life. There's a general wisdom that functional programming helps prevent errors upfront because it places guards around managing state. These guards however, can make I/O very unwieldy to deal with. This usually results in state and I/O management constrained to the smallest sections of code possible, which makes surrounding code easier to write as pure functions that are easy to unit test and verify.
Coming from a backend perspective I have a very clear idea of where state in my systems reside and how I can manage it. I can separate a database query, REST API call, file read, or any other I/O operation from the transformations I want to do on it, and make pure functions out of the latter. In my experience, this has led to software I can quickly modify and verify.
Frontend development however, doesn't have state that can be modeled as single nodes in a larger system. The monitor you're trying to draw to has millions of pixels, and you're responsible for managing all of them. Even in the simpler case of thinking about the browser DOM, you're still managing thousands of stateful entities. This is far more complicated than a database or HTTP endpoint! There was no way this much state could be boundaried, contained and computed via pure functions. Or so I thought. Then I read the official react tutorial.
In React state is managed via its own render loop, which abstracts state away exactly how I think about a database abstracting state. When I write a SQL query I don't care about the details of how I get data from a database, I just care what it looks like. Similarly, instead of caring how React is mutating the DOM under the hood, I just write JSX to declare what the DOM looks like:
```
function WaypointDataPane({setClickedWaypoint, currentWaypoint}:
{setClickedWaypoint: Dispatch<SetStateAction<null>>, currentWaypoint: Waypoint}) {
return (
<div className={"c waypoint-data"}>
<table className={"general-table"}>
<caption>
{`${currentWaypoint.symbol}: ${currentWaypoint.type.replace("_", " ")}: belongs to ${currentWaypoint.faction.symbol}`}
</caption>
<tbody>
<tr>
<th>Trait Name</th>
<th>Trait Description</th>
<th>Trait Action</th>
</tr>
{
currentWaypoint.traits.map(t => {return(
<tr className="selectable-row">
<td>
{t.name}
</td>
<td className={"description-text"}>
{t.description}
</td>
<td>
{t.symbol === "SHIPYARD" ? "Browse ships" : "N/A"}
</td>
</tr>
)})
}
</tbody>
</table>
<button className={"close-table"} onClick={() => setClickedWaypoint(null)}>Close</button>
</div>
);
}
```
Imagine having to spell out all those table rows in a for loop with createElement!
It's not a perfect system. React code tends to have a lot of effect hooks which break the functional paradigm. And communicating state between components can still be a hassle (I have to manage a lot of different mouse clicks and movements on a canvas...yikes!). Maybe my next post will be about how a library like Redux helps alleviate such issues.
This experience has made me curious about other unexpected places functional programming could make my life easer! I don't work with stateful API's or sessions very often 🤔🤔.
If you're curious about the code I'm working on, I've been writing a frontend for the backend game spacetraders.io. Github: https://github.com/ryan-michael-19/spacetrader-gui
<font size=1>Published 2024-04-03</font>