I have a slightly different view of the value of React. It's not the code of the library, per se, but the development patterns. These techniques will work anywhere. If you can get yourself to use them, then React (or anything that works the same way) will be a great boon for you. If not, then you might be better off with something else. Please excuse me for this explanation, which you might already be familiar with.
Imagine your data is in a tree. Go to the very lowest nodes on the tree. You should be able to imagine that rendering these nodes is quite easy. It's just simple data. Now move up a node. Rendering this node is just rendering the data at that level and telling the next level to render. Keep doing that until you get to the very top.
The rendering at every node is now very simple. It is also very easy to write tests for: You just need to make sure that the data in the node has been rendered and that the nodes below are present.
Of course, that's just rendering a static tree. How do we deal with dynamism? In it's simplest form, you don't. Instead, any time you want to change some data in your tree, make a new tree and then render that new tree. This has the advantage that it is very simple. You tree of data is immutable, and so you never have to worry about state changing. At every change you just re-render the entire tree.
Of course, that is costly, so we can be clever and notice that we don't have to re-render the entire tree. We just have to compare the first tree with the second and re-render the highest subtrees that have changed. React does this behind the scenes.
If you are trying to do a kind of hybrid approach of using react for some parts and not for others, this is actually one of the easiest ways to do it. If you want to update your data from the server, you simple make an endpoint for the data at the top of your React tree and every time you change something you make an Ajax call from that top node to get the new data. This will cause the tree to re-render fairly efficiently.
Of course, this doesn't solve all your problems, because often you don't want to get new data from your server, you just want to update data around your tree. In this case, you need to image every node as the top of a subtree. If you want to change the data in the subtree, you simply make a request to the top of the subtree to modify the data in that subtree. This causes the entire subtree to re-render.
So the main flow is that you have a tree of data which you render. Anytime you want to modify the data, you need to make a request up the tree (never sideways and almost never downwards).
These requests can be made in many ways, but the simplest is simply by passing a callback down the tree as a piece of data. You decide which node "owns" a piece of data and then you pass a callback for modifying that data down the tree. Anyone below can potentially call that callback, which will modify the data at the top of the tree and re-render the entire tree.
There are other ways of doing it. Passing a whole whack of callbacks can be tiresome. Flux, for instance, sets up a series of singleton objects that anyone can access. You make a request of the object, it creates a new tree of data and updates the top node of the tree. (Note: Highly simplified explanation to the point of being wrong ;-) ).
Anyway, the point of this is to say that, if you want to write code this way, then you should use React or something like it. If not, you should stay away, because you will make a huge mess.