So here I am again, trying to market the idea of "components". Yes, because project after project, I hear these:
If you're one of the people who get this often and wonder what you can do with such, this might just be your lucky day.
So let's break down the problems and see how components solve these issues.
Why does it work here and not here?
That's probably because your logic in both places are different, when you expect both places to work the same way. Copy-pasted code rarely works the same way, because you will eventually modify it for a certain use case.
Why does this look good here but different here?
That's a styling problem, and made worse given the nature of CSS - it's global. One can easily shoot one's foot just by declaring a style that unknowingly clobbers another style.
I'm sure we tested this already and it worked before. What did you do?
That's regression. And the worst type of regression is when something you checked in caused code half-way around the server to break. It can even happen on code that you never even touched!
So components are self-contained pieces of code that house markup and optionally styling and logic. In a very simple case, they are templates which just render whatever you feed them. In the more complex cases, they morph data and render them beautifully. The major selling-point of components is the fact that they are reusable and self-contained.
Being able to easily reuse a component means that you only have to define them once and be able to use them anywhere. If they break, you can safely assume it's broken on all the other places. Conversely, if you fix one, you fix every single one of them. A framework that properly implements components can easily drop in components anywhere in the app and one can simply expect them to work like advertised.
Being self-contained means that nothing in the outside world should affect a component and whatever you write inside a component can never break the outside world. Both worlds talk via interfaces which both sides consent, no surprises. Additionally, if one writes a component in a referrentially transparent way, one can easily predict what the component does just by looking at the data you feed it.
Components are designed to be generic. It's akin to small Lego bricks. It doesn't know and doesn't care if it gets built into a car or a dinosaur. All it knows is it should connect to other lego bricks. In the same way, a datepicker doesn't care if it's selecting for a birthday or an anniversary, only that it accepts a valid date and returns a valid date.
Business logic is not necessarily absent in components. However, it should be pushed up and away from the components as much as possible. The more specific a component becomes, the lesser the chance it gets used somewhere else. Pushing the logic up increases portability, at the same time forcing your logic to be in one place.
I do, but most people approach code reuse in the wrong way. Most people start out generalizing code and build massive shared codebases. When it comes down to specifics, they fear rewriting those generalized code that they often use duct tape and bandaid code to put up the specific logic into generalized code. This becomes a burden to maintain and you end up writing more code than saving keystrokes.
Components work the other way around. They start small, and assume nothing. If you a specific set of functionality that isn't supported, don't re-engineer the existing components. Instead, one should build another component. The beauty of components comes composability. You don't build your yellow lego car using your yellow lego dinosaur (and be both at the same time). You build them separately, with the same yellow colored bricks.
My component-building days are far from over. I still deal with the same stuff, albeit in another framework. More challenges, more quirks, and a whole lot of... WTF!?!?