I ruined my React components by using optional props
Tags: react, beginners, typescript, webdev
Published: 2022-12-20 16:20:02

> I ruined my React components by using optional props

When I made components, I was trying to make components as flexible as they could using optional parameters. But I found out that it was absolutely wrong.

There were too many options and I wasn't sure what I was going to use to make the component work properly.

I also used unexpected default values a lot. It makes plenty of unnecessary defensive code and I couldn't expect what default values it has.

I will show you some examples that are similar to the mistakes that I made.

---

Let's say, there is a Button component like below.

```typescript
import { ReactNode } from 'react';

type ButtonType = 'primary' | 'secondary';

interface ButtonProps {
  children?: ReactNode | string;
  onClick?: VoidFunction;
  type?: ButtonType;
}

const Button = ({ children, onClick, type = 'primary' }: ButtonProps) => {
  const bgColor = type === 'primary' ? 'red' : 'blue';

  return (
    <button style={{ backgroundColor: bgColor }} onClick={onClick}>
      {children}
    </button>
  );
};

export default Button;
```

Let's see if the optional props are used properly.

* `children`, `onClick`: All we know button can be used without text and click event.
* `type`: There are two options `primary` and `secondary`. We can expect from the name that `primary` would be used if we don't pass the prop. 


```typescript
import { ReactNode } from 'react';

type ColorButtonColor = 'red' | 'blue';

interface ColorButtonProps {
  children?: ReactNode | string;
  onClick?: VoidFunction;
  color?: ColorButtonColor;
}

const ColorButton = ({
  children,
  onClick,
  color = 'red',
}: ColorButtonProps) => {
  return (
    <button style={{ backgroundColor: color }} onClick={onClick}>
      {children}
    </button>
  );
};

export default ColorButton;
```

This button has the `color` prop instead of `type`.
`color` has `red` as a default value.

The button might've had the default value for a purpose. For example, `red` might've been the most used.

But no one can expect that. In this case, it would be good that `color` does not have a default value.

---

Here is another example.

```typescript
interface ListProps {
  items?: string[];
}

const List = ({ items = [] }: ListProps) => {
  return (
    <ul>
      {items.map((item, itemIdx) => (
        <li key={itemIdx}>{item}</li>
      ))}
    </ul>
  );
};

export default List;
```

We can know `List` is a general-purposed component.

```typescript
<List />
```

You render it and If there is nothing shown, you would know if you forget passing a prop.

Look at another list component.

```typescript
type UserListItem = {
  nickname: string;
  intro: string;
};

interface UserListProps {
  users?: UserListItem[];
}

const UserList = ({ users = [] }: UserListProps) => {
  return (
    <ul>
      {users.map((user, userIdx) => (
        <li key={userIdx}>{`${user.nickname} | ${user.intro}`}</li>
      ))}
    </ul>
  );
};

export default UserList;
```

It's the same as the previous one without the type of item.

```typescript
<UserList />
```

If it doesn't have an error, can you know what it is wrong out of the box?

Someone may think `UserList` has a business logic and it displays the user list itself.

But it needs the prop `users` to display the user list.
If `users` is not optional, you must be able to know what is wrong and it would be going to save you time.

---

When it comes to function properties, it's also the same.

```typescript
interface NavbarProps {
  onSetting: VoidFunction;
  onProfile: VoidFunction;
  onHome: VoidFunction;
}

const CornerNavbar = ({
  onSetting,
  onProfile,
  onHome,
}: NavbarProps) => {
  return (
    <ul>
      <li onClick={onSetting}>Setting</li>
      <li onClick={onProfile}>Profile</li>
      <li onClick={onHome}>Home</li>
    </ul>
  );
};

export default CornerNavbar;
```

`CornerNavbar` has function properties and without these functions, the component wouldn't work as intended. You shouldn't make them optional.

If you defer to implementing some properties, you can use comments and temporary functions.

We can use HTML tags without passing event functions like `onClick`, `onLoad`, `onMouseDown`. I think the fact was confusing me.

---

## Conclusion

These might be considered beginner mistakes and some of you might have your rules to cover this situation other than what I explained.

Although I have been using `typescript`, I was getting rid of an advantage of it myself. My opinion that I said in this post could be wrong though, I have learned from it that it is important to keep thinking about what I am used to.

I hope you found something useful in my article.

Happy Coding!