It all begins with the planning.

If one has planned good enough, gone through every scenario in their heads and considered the near infinite possible states their UI can be in, a resilient, future proof and highly modular component can be designed and it’s powers can be enjoyed for years to come.

Regimes change. New faces emerge. Our component only adapts as required. No refactor needed. Ever.

…

While this is all good in theory, reality paints a slightly different picture.

There we have a business guy who wants a feature out yesterday; the designer created an impossible mockup with dragons flying all over the place and finally the marketing onboard a fat corporate client with the promise of a family of feature set: few already present and about 80% to be delivered over 2 months.

You are a team of 2 frontend engineers: understaffed, yes but you are given a chunk of this work, of course with a mission impossible like time constraint.

While all of this is going down, you have to first figure out a solution for the said problem statement, how you are going to handle immutability or maybe if it is a new project, what tech stack + framework + library to use.

Let us consider a simple use case: render an input with a count vs max allowed length. Somewhat like this:

Input with character count / max allowed length

Simple enough, right? You already have a generic Input component and it is a matter of adding some configuration showConstraint to it. Maybe like this:

<Input maxLength={100} value={value} showConstraint />

You perform some dark magic and the input finally begins working. So far so good.

Problem creeps in when your PM goes nuts and asks you to bring the same behaviour to something ridiculous like maybe a textarea or a draftjs input.

Now your count is deep wired to input and you either have to rewrite for textarea & draftjs or maybe extract it somehow.