HTML forms with multiple buttons

Lets say you have an HTML form with multiple buttons. One button submits the form, but the others do something else. Here’s a simple example:

<form>
  <label>
    Email address
    <input type="email" name="email" />
  </label>
  <button onClick="handleCancel()">Cancel</button>
  <button>Save</button>
</form>

I might type my email address into the form, press Enter, and… oops. For some reason, pressing Enter chooses the Cancel button.

The fix is to add type="button" to any button which should not submit the form, and type="submit" to any buttons which should submit the form, like so:

<form>
  <label>
    Email address
    <input type="email" name="email" />
  </label>
  <button type="button" onClick="handleCancel()">Cancel</button>
  <button type="submit">Save</button>
</form>

Pressing Enter will now submit the form, as expected.

Electric milk floats

When I was a kid, we had milk delivered to our door every day. There’s plenty to be said about that, but today’s point: It was delivered by an EV, and at the time it was completely normal.

When I was growing up in the 1980s, we had fresh milk delivered to our door every day, by someone driving an EV. At the time that was completely normal. Over time, those EVs just faded away.

The EV design was chosen in part because they’re quiet (especially compared the the diesel and petrol engines of the time) – the milk was being delivered to residential streets in the early hours of the morning.

Unigate Milk Float
Unigate Milk Float by f1jherbert on Flickr.

There’s a lot of buzz around the likes of Amazon and UPS ordering huge numbers of EV delivery vehicles from companies like Rivian and Arrival. These things are super cool and potentially transformative, but the concept isn’t exactly new. Specialist electric vehicles designed for short hop (or last mile) deliveries in towns and cities have existed for nearly a century. It turns out Wales and Edwards started making these things in the early 1950s, and Morrison-Electricar were building them as far back as the 1930s.

We just forgot about them for a while.

Using Flow types with Reach Router route components

I have a project which uses Flow for static typing, and Reach Router for routing. Reach Router uses Route components to assign components to URLs:

<Router>
  <Component path="/somewhere" />
  <AnotherComponent path="/somewhere-else" />
  <YetAnotherComponent default />
</Router>

So if you browse to /somewhere-else, <AnotherComponent /> will be rendered. So far, so good. However, if one of these components doesn’t accept any props, Flow will complain:

export const AnotherComponent = () => {
  return <>I am another component.</>;
};

Error:(116, 10) Cannot create AnotherComponent element because property path is missing in function type [1] but exists in props [2].

To work around that, I created a Route component and a DefaultRoute component:

// @flow

import type { DefaultRouteProps, RouteProps } from "@reach/router";
import * as React from "react";

type RouteComponentProps = RouteProps & {
  component: React$ComponentType<*>,
};

type DefaultRouteComponentProps = DefaultRouteProps & {
  component: React$ComponentType<*>,
};

export const Route = (props: RouteComponentProps) => (
  <props.component {...props} />
);

export const DefaultRoute = (props: DefaultRouteComponentProps) => (
  <props.component {...props} />
);

(Note the imported types are pulled from flow-typed‘s Reach Router definition).

They’re used like so:

<Router>
  <Route component={Component} path="/somewhere" />
  <Route component={AnotherComponent} path="/somewhere-else" />
  <DefaultRoute component={YetAnotherComponent} default />
</Router>

(And yes, eventually we’ll likely migrate this project to React Router.)

This is my jam

React’s useEffect and arrays in its’ dependency array

Could I get any more arrays into that title? I’m working on a React app at the moment. Adopting hooks has made my life a bit easier. But useEffect‘s dependency array took a while to get my head around – specifically what to do if your only dependency is itself an array.

If useEffect‘s dependency array itself contains an array, like this, you get an infinite loop and effectively perform a DOS attack on your own API.

const Thing = () => {
  const [arrayOfThings, setArrayOfThings] = useState([]);

  useEffect(() => {
    // Imagine some code here to 
    // fetch things from an API
    setArrayOfThings(loadedArrayOfThings);
  }, [arrayOfThings])

  return (
    <ul>
      {arrayOfThings.map(el => (<li>{el.title}</li>))}
    </ul>
  )
}

I imagine it’s because useEffect isn’t doing a deep compare on the dependencies. So, perhaps changing it so useEffect is dependent on the length of the array will help?

useEffect(() => {
  // Imagine some code here to
  // fetch things from an API
  setArrayOfThings(loadedArrayOfThings);
}, [arrayOfThings.length])

Well, it does, but it still requests the data from the API twice – once on first render, and again after the first fetch because the length of the array changes. The fix I found is to use a second useState variable:

const Thing = () => {
  const [arrayOfThings, setArrayOfThings] = useState([]);
  const [doFetchData, setDoFetchData] = useState(true);

  useEffect(() => {
    if (doFetchData) {
      // Imagine some code here to 
      // fetch things from an API
      setArrayOfThings(loadedArrayOfThings);
      setDoFetchData(false)
    }
  }, [doFetchData])

  return (
    <ul>
      {arrayOfThings.map(el => (<li>{el.title}</li>))}
    </ul>
  )
}

The ensures the data is only loaded once. Additionally, it gives us a way to precisely control when to go and re-fetch the data (using setDoFetchData(true)). Better.

Use React.memo() wisely

Use React.memo() wisely by Dmitri Pavlutin is the article which finally made React.memo() click for me.

(Thanks for sharing, Remy.)

An encounter

We were out riding our bikes in the local forest the other day. I took a wrong turning and was cursing because it meant missing a particularly fun section of trail.

But then we came around a corner, and there was a very large and beautiful black bear wandering down the track ahead of us.

I stopped in a hurry, and Andrea, confused, pulled up alongside me. “Bear! Bear!” I said, gesticulating wildly, which had entirely the wrong effect – Andrea got all excited and wanted to go and give him a hug. The bear paused and looked over his shoulder at us. We shouted “Hello Bear!”

He turned, gave us a long hard stare, nodded, then carried on up the track and off into the trees.

These encounters aren’t that unusual around here, although they happen quite a lot less often than they used to.

This is my jam

Another one from Orkidea. When I’m singing this tune in my head I “hear” the Perfect Motion lyrics laid upon Simple Minds’ Theme for Great Cities.