DEV Community

Sid
Sid

Posted on • Updated on

Don't create conflicting props

This is part of a series of posts about writing component API for great developer experience.

This post was originally posted on my newsletter a few weeks ago, just saying.

This is one of the easier ones:

We have a button here:

button-1

<Button>Click me</Button>
Enter fullscreen mode Exit fullscreen mode

You probably also need a primary button to serve as your main action on a page. I used to like shaping the API just like you would say it - "Give me a primary button"

button-2

<Button>Click me</Button>
<Button primary>Click me</Button>
Enter fullscreen mode Exit fullscreen mode

So pretty.

Now, as it goes with buttons, you probably need a few more. Here's what the props table ends up looking like:

name description type default
primary used to indicate the main action boolean false
secondary used for actions which are less important boolean false
destructive indicate that the user should be cautious, example: delete boolean false
link used to style button similarly to a hyperlink boolean false

There are multiple props that can be used to change the appearance of the button. What is the expected outcome if someone uses them together?

button-3

<Button primary destructive>
  Click me
</Button>
Enter fullscreen mode Exit fullscreen mode

Will one of them win, which one? Is it dependent on the order?

I would always ask: Why would someone write that? Is this even a real use case - "Give me a primary destructive button"?

Most of the times, this would be by mistake. But, if the developers have to ask questions like the ones above, it's probably not a good API.

As someone who is deciding the API, it's your job to:

  1. minimise mistakes
  2. minimise confusions around the API

So here's tip #1 for you: Don't create conflicting props

We can fix our above code pretty easily by using one prop which allows a list of options: appearance

button-4

<Button appearance="default">Click me</Button>
<Button appearance="primary">Click me</Button>
<Button appearance="destructive">Click me</Button>
Enter fullscreen mode Exit fullscreen mode

We can add a list of supported appearance using prop-types.

Button.PropTypes = {
  appearance: PropTypes.oneOf(['default', 'primary', 'secondary', 'link', 'destructive'])
}
Enter fullscreen mode Exit fullscreen mode

Now, even if the developer makes a mistake, they will get a helpful warning on their developer tools.

button-1

<Button appearance="danger">Click me</Button>
Enter fullscreen mode Exit fullscreen mode
Warning: Failed prop type:
Invalid prop `appearance` of value `danger` supplied to `Button`,
expected one of `["default","primary","secondary","link","destructive"]`
in Button
Enter fullscreen mode Exit fullscreen mode

This tip is pretty easy to implement, but will make your API a lot easier to use (and maintain).

Hope this was helpful on your journey

Sid


newsletter

Top comments (1)

Collapse
 
dance2die profile image
Sung M. Kim

Thanks, Sid.

The tradeoff was made (appearance a bit more verbose) but the outcome outweighs what's lost 👍.