The biggest cause of bugs before we used React is the fact that the "state" of the app is leaking all over the place. Symptoms were things like looking for dom nodes that didn't exist, events that triggered on code that was no longer active, bugs due to the app being in a state extremely complex to reproduce with crazy conditions all over the place, race conditions...
React does many things to mitigate those problems and those classes of bugs nearly dropped to 0.
- The code you write is declarative: you say how you want the dom to look like. This means that you no longer have two pieces: creation and retrieval that need to be kept in sync.
- React manages the life cycle of the components. When the component is no longer being rendered, it is properly destroyed, all the listeners are destroyed ...
- The render function is pure. This means that it is easier to write and unit test.
- The code is organized into small, composable and unit testable modules. By having a lot of small components it makes writing complex bug-free code easier.
- Each component has a very well defined interface. It cannot use anything else without it being obvious. This prevents the creation of big chunks of interdependent modules that are impossible to separate.
- There is a single point for state update. This makes the high risk pieces of code stand out.
In the end, we found that React actually helped us write more reliable app compared to framework-less Javascript code.