Not because they are so great but because everything else is even worse.
After significant React experience I can no longer tolerate send-html-template-sprinkle-javascript stacks.
The downside is that the amount of boilerplate is unbearable. There's significant friction in the tooling because of transpiling, sourcemaps, multiple layers of sourcemaps, file watching, having to produce multiple different bundles for server side rendering, client-side bundle and so on, testing with transpiling is a pain, test coverage with transpiling is at times borderline impossible, proper isomorphic data-loading is difficult and the list goes on. Still prefer it to the other stuff.
Even if they are extremely familiar with the tooling it's still a huge problem.
People get seduced by unrealistic examples online and think "oh easy just drop this little config thing here and done".
The problem is the little things pile up on top of each other before you know for a production app you are deep into plugins and transpilers and configs to your knees and you have to make them all play with each other.
Just some examples of difficulties of this architecture,
- You must have an API for doing anything because the client-side needs the API, but on the server you also have to use the same code for server side rendering. It gets more fun because you have to deal with authentication as well on both sides. So you will have to "proxy" the cookies from the client on the server side to the API to load initial data for server side rendering. This is full of gotchas and largely undocumented it will take you at least multiple days to get right.
- Data loading for client-side navigation is tricky. At what point do you fire ajax calls to load data for the destination? Sometimes multiple calls are needed. With react router you'll need a custom "Link" component with data loading functions that produce promises then you can do Promise.all on them and transition when ready. For a good experience you have to incorporate timeouts. In my case I immediately start loading target data upon link click for navigation, wait up to 100ms ("navigation wait tolerance") and if things are not done by then I navigate to the target in a loading state and the page re-renders when data is loaded or error happens and error is displayed. Again, full of gotchas.
- Need an admin panel? well you better not have any potentially sensitive text on your admin pages because guess what that ASCII text is going right into your javascript bundle. This is a minefield if you don't want to be leaking your admin UI and capabilities. At this point you will need to have a separate admin bundle that is not given to normal users. Good luck with that. You can't just "add" it on top of the normal bundle (too hard to explain, try it and you'll find out). So it needs to be a complete application bundle that is built for admins. But well if you want the admins to go through the normal login page like all the other users ... gotta switch somewhere in there.
- Testing? Forget about all the usual CLI tools like mocha/jasmine/ava/jest/etc... they will all blow up one way or another when facing a sufficiently complex application with webpack/jsx/transpiling/etc. So you have to have another "test" bundle that imports all the tests, you have to transpile and build that bundle then execute it with a test runner. At this point all the usual tools for test coverage become nearly unusable.
- Server side rendering: since your client-side stuff like React components are also needed on the server now you need to be building a server side rendering bundle and then you have to constantly keep running the output of that build so your server-side-rendering during development works correctly.
These problems will interact with each other in complex ways you can't just solve them separately one by one. Each one you try to fix will create other compromises or problems in another area.
In summary, it's an absolute cluster fuck and I challenge anyone who think it's easy to do a non-trivial project complete with user signup/login/logout/admin panel/authentication/authorization/roles/server side rendering/tests and come back.
And with all of this bullshit I still prefer this to the old(er) way of jQuery event handlers and so on.
At some point I got so fed up with the problems I described earlier I tried to go back to the old stuff but I couldn't tolerate it anymore so I came back and accepted the new nonsense.
Mind you it has improved a lot since the last year as well. Especially with the newer versions of React Router.
Sounds like you might like Clojurescript + Reagent which is based on React but with much simpler tooling (Leiningen). You can also run Clojurescript on Node now with Macchiato (https://macchiato-framework.github.io). If you need something CPU-heavy you can hook it up to a backend API written in Clojure. Turtles all the way down :)
This seems like a lot of independent concepts to grok + configure to create a webapp. Especially when a viable alternative might be PHP +Postgres + jQuery. I guess I'm just old and cranky anymore :)
Believe me I used to do lots of PHP+Postgres+jQuery but after experiencing React I just feel like shooting myself after writing some CSS selectors and binding event handlers.
It feels like trying to start a fire with a stick when you have a lighter in your pocket.
But as I said the boilerplate and friction is still unbearable.
Not because they are so great but because everything else is even worse.
After significant React experience I can no longer tolerate send-html-template-sprinkle-javascript stacks.
The downside is that the amount of boilerplate is unbearable. There's significant friction in the tooling because of transpiling, sourcemaps, multiple layers of sourcemaps, file watching, having to produce multiple different bundles for server side rendering, client-side bundle and so on, testing with transpiling is a pain, test coverage with transpiling is at times borderline impossible, proper isomorphic data-loading is difficult and the list goes on. Still prefer it to the other stuff.