React, Hooks, & The Death of Redux

I did it, I finally stopped procrastinating and moved to writing all of my react code with functional components, managing state with hooks. My only question during the entire process was why did it take so long for me to do it.

I suppose that question particularly focuses on my unwillingness to change to use a new paradigm. Having said that, in the world of Javascript, it’s not a bad habit to have. Libraries come and go, but only the good ones stick around.

I think my primary hesitation was my strong dislike of the learning curve associated with Redux. Most people complain about the boilerplate, and despite what some elitists think, it’s a valid criticism. And while I agree with Redux’s philosophy its execution is what inevitably leads for people(even a long time user like me) to search for alternatives.

Rather than leave it there, let’s dive into that particular failing of redux. Mostly because it’s glossed over but also because I don’t like their explanations of how to reduce it (pun intended).

For the uninitiated typically in a react application with react, you’ll bind your react app to the redux container like so:

// index.js
import React from 'react'
import ReactDOM from 'react-dom'
import TodoApp from './TodoApp'

import { Provider } from 'react-redux'
import store from './redux/store'

const rootElement = document.getElementById('root')
ReactDOM.render(
  <Provider store={store}>
    <TodoApp />
  </Provider>,
  rootElement
)

Then in every component you’d like to access the container you need to do something like the following:

const mapStateToProps = (state, ownProps) => ({
  // ... computed data from state and optionally ownProps
})

const mapDispatchToProps = {
  // ... normally is an object full of action creators
}

// `connect` returns a new function that accepts the component to wrap:
const connectToStore = connect(
  mapStateToProps,
  mapDispatchToProps
)
// and that function returns the connected, wrapper component:
const ConnectedComponent = connectToStore(Component)

// We normally do both in one step, like this:
connect(
  mapStateToProps,
  mapDispatchToProps
)(Component)

And you haven’t even gotten to actually writing the logic of your state or components! Comically the suggestion to avoid this is to use syntactic shorthand:

import {addTodo, toggleTodo} from "./todoActions";

const mapState = () => {}

const mapDispatch = {addTodo, toggleTodo};

export class TodoList extends React.Component {}

export default connect(mapState, mapDispatch)(TodoList);

Notice how that is the same number of steps? I did, but I digress the issue isn’t with Redux, it’s in the binding to React. Enter hooks. Using a library like reactn, I can simply use hooks in tandem with a custom context and provider to do the following.

import React, { useGlobal } from 'reactn'; // <-- reactn
import Card from '../card/card';
 
// Render all cards in the global state.
const Cards = () => {
 
  // Use the hook to get all cards in the global state.
  //   setCards is not used in this example.
  const [ cards, setCards ] = useGlobal('cards');
 
  // For each card in the global state, render a Card component.
  return (
    <div>
      {cards.map(card =>
        <Card
          key={card.id}
          {...card}
        />
      )}
    </div>
  );
};
 
export default Cards;

Obviously this only works for simple set and forget values, but using reducers we can achieve the same functionality that redux has, using the same paradigm with hooks.

import React, { useDispatch } from 'reactn'; // <-- reactn
 
const incrementReducer = (global, dispatch, action) => ({
  count: global.count + action.amount,
});
 
const decrementReducer = (global, dispatch, action) => ({
  count: global.count - action.amount,
});
 
const MyComponent = () => {
  const increment = useDispatch(incrementReducer);
  const decrement = useDispatch(decrementReducer);
 
  return (
    <div>
      <button onClick={() => increment({ amount: 1 })}>Add 1</button>
      <button onClick={() => increment({ amount: 3 })}>Add 3</button>
      <button onClick={() => decrement({ amount: 5 })}>Subtract 5</button>
    </div>
  );
};
 
export default MyComponent;

I’m looking forward to writing less code and doing more, which is the whole point of this long rant about state management. The less boiler plate I have to write the more time I spend actually making things, which is pretty cool.

Laravel & Angular: Batteries Included

Online you will find no shortage of people claiming they know the correct way to do things. That you should use technology x or y or z because it’s the most correct way to do things. But often I’ve found that correct is usually an metaphor for the way the someone prefers to do things. This is in place of practicality and often ends up doing more harm then good, as new developers adapt technologies they do not understand. So I’d like to propose a new metric for correct, practicality.

The Idea:

This particular setup is a tad unusual but not unheard of, the primary reason being that it takes a little finagling to get it setup correctly. But once it’s setup, you can prototype and deploy an application very rapidly. The idea is to use an Angular SPA for the client and Laravel w/ Apache/NGINX for the API.

Angular:

There are a bazillion different front-end frameworks, why Angular. In truth you could get good mileage from any of them. However Angular(and possibly Vue soon) provides you with just about everything you need out of the box. It is a Top to Bottom framework, it’s opinionated in a good way and dictates good application structure with excellent build tools and clear documentation. In addition to a growing community, support is easy to find.

Laravel:

I feel like I don’t need to sing it’s praises but with some of the best documentation in the open source world, and probably the largest framework development community, you’d be hard pressed to find an easier framework to work with. It may not be the fastest but it is the fastest to write with, and I can’t think of a better framework to jump-start a clean project.

What You Get:

The end result is a batteries included project and ecosystem of libraries and tools that are battle tested for the web. These frameworks force you to write code a certain way, which may not be for everyone, but is great for getting an idea to market.

Stop doing things manually. Please.

I am by no means experienced in my field, however this doesn’t seem to stop my peers from thinking I have some form of magical knowledge about how to rapidly deploy applications. The truth is I don’t employ some special knowledge to do things faster, much to their surprise I simply follow convention.

My philosophy is this, as good as I am in my field, I simply do not know everything. So I trust the experts who specialize and trust their advice in that field. One such idea is that you should avoid doing things manually and repetitive. The benefits of automation should be self evident of those in the field of programming, but experience and interaction reveals that many a programmer is perfectly content to do the same task over and over again.

The most common explanation is inexperience or ignorance, this I believed for the longest time as it made the most sense. I mean no one would do extra work if the didn’t have to…. right? Wrong, I personally know several brilliant engineers and developers that would manually copy over files while testing code for a project. When I say manually I don’t mean through a script with a command. No. I mean opening explorer in Windows, navigating and copying files over then closing the explorer window and repeating the process after a code change. I’ve seen someone do this whilst working on a neural net, it hurts to watch.

So much time is wasted simply by not having a build/deployment process. What may seem like only a few seconds of time adds up when you do it over and over again. It only takes a few minutes to setup proper tooling.

Take web development for example: if you find yourself reaching for an ftp client, stop yourself and ask why not use a shell script, and more importantly why aren’t you using an encrypted file transfer program? If you find yourself constantly changing file permissions or file context, why not write the command once in a script?

The first thing I hear from a never change my ways engineer is that they simply don’t want to maintain another script. That’s fine, use a CI/CD system and have it maintained for you. Most modern deployment systems even let you simply add a file to your VCS repository and track it as you make changes to your deployment process(awesome).

The point is, when you find yourself doing something over and over, take a minute and ask yourself. Could I save some time?

Jumping Hurdles with Heroku

Just for fun I decided to take on a small micro project. I see websites all over the internet that let you enter in the url of a youtube video and download the video. I wanted to make a basic, no frills recreation of that and do a fun little 100 lines or less project, the following is what happened.

First I picked a platform, Heroku was the obvious choice as free hosting as it turns out is the right price. Since I already have a domain so I can easily add a CNAME record to my main website’s host file and add on a simple subdomain in this case youtube-download.treyfoster.com. I decided to go with Heroku’s docker deployment configuration, more on that later.

Laravel was an easy choice as it’s simple enough to setup a quick project. Moving to the library to power the project. I suspect most of these websites use youtube-dl a popular python program that gives the user a host of options in how they want to download the file. You can select what format you’d like the video in (it uses ffmpeg as the default converter).

At first I thought I would take a jolly swing at writing a wrapper, however a simple search revealed there was no need as a wrapper library already existed so I ended up using that instead. All that was left to do was rig up a simple controller and I was off to the races. Here’s a primitive version of it which basically does what I wanted:

The next part was getting this to run on Heroku, the default PHP image that Heroku deploys quite obviously does not include the Youtube-dl binary. Luckily Heroku supports docker which means we can have it run whatever image we damn well please. Here is the Dockerfile I finally rested on:

It’s basically just a pull of an image which pulls in all of Laravel’s dependencies, I then just run the Youtube-dl install script and kick it off back to Laravel. Is this the most elegant thing in the world? No, but the process does show how easy it’s becoming to deploy apps. The entire process only takes about thirty minutes from conception to being a usable albeit primitive application.

macOS No Longer Ships with Scripting Languages

I cannot tell you how happy I am right now, Apple has decided to remove scripting languages from the base install and internalize the legacy functionality that those dependencies provided. While this might seem like small news, for programmers on Macbooks and there are a lot of them it’s a much welcome and much needed breath of fresh air. The update provides two major benefits, one making the life of a programmer much easier.

For those of us that use Homebrew, this really is great news. You see the problem this update solves is that most new python programs use version three, while the OS ships with version two. That means that whenever you want to use python you have to use the clunky and redundant python3 command, bleh. But now when we install python3 we can just use the python command beautiful.

In addition to the obvious benefits, this undoubtedly adds security and performance benefits as keeping mostly unused older versions of scripting languages has some obvious exploits. Plus internalizing the dependencies is just the right thing to do long term, it makes for a more maintainable code base for the macOS team, with reduced number of languages to deal with, and less external dependencies to worry about.

Diving into A Serverless Application

For the uninitiated, a serverless application is one that obviously still runs on servers but runs as an application via a service providers various automatically managed computational resources. All of that jargon essentially means that you can write code and not worry(too much) about the infrastructure as it is managed for you or via code. Today I’ll be sharing some pains and pleasures of working with the serverless framework, one of many frameworks that let you easily take advantage of a multitude of provider’s cloud resources.

IT JUST WORKS

It really does. Assuming you know what you are doing(more on assumptions later), you can easily get a simple REST API up and running with very little difficulty. I was able(using node) to get a basic ordering system up in about 15 minutes. I was using AWS, it spun me up an API Gateway, Hooked it up to my lambda functions and I was off to the races. Another thing that just worked was ENV Variables(though AWS Secrets Manager gave me some trouble initially).

BUT NOT REALLY

Serverless Framework assumes a great many things, like for instance that you won’t be serving binary assets through your application. The general solution to this problem is to serve your website as a static website and have it consume a separate API. That’s fine, I just wish there was a well documented tutorial on how to set that up(blog post pending). Another thing is database migrations(not an issue for NoSQL people). For those of use who have relational data this can be a show stopper. My solution was quite elegant, however undocumented and pretty much freestyle.

If you couldn’t tell, my biggest problem with serverless right now is the lack of documentation, but that’s most likely because it’s so new. Perhaps it’s on the early adopters (ie. myself) to make the tutorials to open up the space a little. I’ll commit to trying to explain some of these things in future posts and tutorials.

Lasting Stability: An Argument for Frameworks

A common type of medium article I’ll see lately is something to the effect of: “Why not to use a JavaScript Framework”, “Why ever use a JS Framework”, or my personal favorite “You probably shouldn’t use a JavaScript Framework”. While it is certainly true that a great many websites do not make use of frameworks, an equally great number do. But ultimately the question that is begging to be asked is: Why bother with frameworks at all? 

Frameworks like any programming paradigm were made to systematically solve problems in a structured format. Though many different frameworks exist and they all use different structures to solve similar problems, it’s the structure that matters. That’s not to say that any structure should be valued, as with any strategy in problem solving it should be scrutinized. A framework should put through a crucible of rigorous testing to make sure it actually solves the problems it sets out to solve.

However I see a recent trend of developers crying out against frameworks as if they seem to be useless technical baggage. The irony is that technical baggage is exactly one of the issues they set out to solve. The structure of a framework does bring extra weight and initial legwork to build applications(although not really since scaffolding tools solve this for the most part). However unless the project is a static web page that needs no customization(which is a non starter in any business setting) then the framework tends to enforce structure that reduces technical debt over time.

Any developer worth his salt knows that Feature Creep is a major problem, Frameworks don’t solve that problem(only proper communication can) but they do help with extendability and scaleability. So even if a project’s current needs to do not merit a framework, if the project has any long term goals the chances that it will eventually are exponentially high the longer the project’s life goes on. Trust me, you don’t want to find out 4 years into a project that the entire project needs to be redone in a framework and sometimes a different language if you levy Typescript.

I don’t want to come off as saying Frameworks solve all of your problems, because they sure as heck do not. But I do think that any serious web project would be silly not to leverage the tools, scaleability and functionality that Frameworks offer in the modern development world.

Why Rust’s Documentation is on My Suggested Reading List

If you haven’t read the Rust Book from the Rust website, please go do so now. Including a docs website on my reading list was kind of a weird decision. For the most part documentation is dry and usually for people who know what they are looking for, the concepts behind the documentation are usually left to the third party tutorial makers(with some notable exceptions). But the Rust Docs are completely different. Read more

I didn’t know I needed CI/CD until I met Jenkins

Manual deployment sucks, plain and simple. Humans are prone to error and make mistakes all the time, but get it right once and do it the same way consistently? That’s the attraction of a CI/CD system like Jenkins. Read more

Much Ado About Nothing

It’s that time of year again, where some apocalyptic headline crosses my news feed and I shake my head in silence at the lack of foresight most of my peers seem to have. I don’t claim to have some magical insight into the future, but some common sense goes a long way in preventing anxiety.

Read more