Never let your React components accept a style property: it forces the developer to know the internals of your component and makes it difficult to refactor.

The domain

When implementing React components, it’s easy to end up with code like this:

The style property allows the component’s consumer to inject arbitrary style, hence controlling how the component is rendered.

It enables the developer to obtain the desired result, and at the same time forces her to know the details of how Avatar is rendering.

The problem

The first issue with this shortcut is that the developer needs to know how the component works internally.

To be able to modify the inner structure of a component via styles, a developer must read the component itself, line by line, and therefore make assumptions about the way it is rendered.

Once the team starts working on those assumptions, refactoring a component becomes difficult and sometimes impossible.

Suppose that we decide to add a new feature to the Avatar component, a name:

Since the developers are relying on the rendering result of a component, any update to its structure can break the result: how will the additional style of my outer <View> affect the existing custom styles? The only way to know it is by checking each affected screen, for each of the involved states.

Or more likely, your users will find it out before you do.

The bottom line

First things first: gather the requirements before coding.

Once you’ll have formalized the requirements for your component, you can pass specific properties:

  1. the border color must be different on this screen? Introduce a borderColor property
  2. there is a place where the avatar is not centered, but aligned to the left? Tell it via an alignToLeft property
  3. …and so on

Our component could now have a shape like the following one:

Naturally, this requires more time than hijacking the component via styles nonetheless results eventually in more maintainable and testable code.

What if my requirements are too broad?

In this case, a component is a wrong choice: you shouldn’t have shared code if there is no shared intent.

Better to break it apart and use an ad-hoc solution for each scenario, and see if a common pattern emerges naturally over the time.