Card image cap

ULISES
RAMIREZ-ROCHE

  • Software Developer
  • Javascript Specialist

Prop Swarms develop on the outer shell of a component like hordes of piranha gnawing at your hippocampus. As with other anti-patterns of the Goldilocks genus, it’s easy to spot when it concedes the center; look for the blood-stained sprawl the size of suburbia you must hack through with a machete.

The infestation is slow at first. Software, unlike war, changes all the time. The app needs to do more today, or it didn’t get it right yesterday. Over time, as code is passed around like a puck, props will append to the component, the reasons behind their existence forgotten before the tides shift like the everyday fabric of human folly.

If there are no tests, as is often the case, it will be hard to justify removing any prop due to the risk of unintended side effects. The brood will breed, and eventually, they will puncture the shell, and the component will be a lair to all sorts of bugs and poltergeists.

IRL

This anti-pattern appears in the wild as a  mass number of props being passed down to a component. You’ll find objects, inline-functions, references, to helper functions, variables, computed properties, and any other arcana you can think of all on the same level, bursting the components exoskeleton.

A Prop Swarm can be a telling sign of a Titan Component, but not always. Sometimes it may just be a sign of infection. However, its best to destroy the swarm before the infestation grows and the  swells it into a collusus.

Healthy Component

class EarlyAdopterRegistration extends React.Component {
  render(){
    <UserSignupForm
      user={user}
      onSave={this.saveUser}
      onSuccess={() => Mailer.welcomeToTheJungle(user) }
      onCancel={this.cancelUser}
      onError={(e)=> {Actions.failWhale(e); }}
      options={{
        isBeta={true}
      }}
    />
  }
}

Component infected by a Prop Swarm

class EarlyAdopterRegistration extends React.Component {
  render() {
    <UserSignupForm
      userEmail={user.email}
      userPassword={user.password}
      userPasswordConfirm={user.passwordConfirm}
      userName={user.name}
      onSave={()=>{
        const isValid = Actions.validateUser(user);
        if (!isValid) {
          const error = new Error("User isn't valid")
          return Actions.alertError(error);
        }
        return this.saveUser().then((user)=>{
          Mailer.welcome(user);
        }).then(()=>{
          Actions.alertSuccess("Congrats!");
        })
      }}
      isBeta={true}
      userIsEarlyAdopter={true}
      onError={this.handleError}
      onSuccess={this.handleSuccess}
      onCancel={()=>{
        const ok = confirm("Are you sure?");
        if (!ok)  return false;
        return this.cancelUser();
      }}
      mailer={Mailer}
    />
  }
}

Strategy

Enforce a Props Limit

Set an in-house rule that puts a hard limit on the number of props that can be passed down to any component.  Find a number you find reasonable, maybe seven or eight, whatever’s your lucky number. The idea is to keep the surface area small.

Fail code reviews if someone crosses the red line. Better yet, write a custom rule, so the linter yells at you the moment you do, and it becomes a habit.

Avoid Inline Functions

Use an instance method, or a full-fledged action if necessary,  but don’t write the function inline. The code size component will balloon out of control and murk clarity.

Namespace Props

You can group related props by context into a single prop which then acts as a namespace. You’ll want to be judicious, of course, but don’t forget that namespaces are one honking great idea and we should do more of those.