Usually people say “dirty checking” when they mean “keep checking in some kind of event loop whether external entity modified some object, and if so, do something”.
In React there's no such event loop where it checks virtual DOM—React knows if it needs to compare virtual DOM trees (not arbitrarily check models for changes, for example) because all changes are explicit and happen either due to `setState()`, `forceUpdate()` or `React.render()` top-level call.
So React doesn't do dirty checking in the sense Angular does, unless by dirty checking you mean all kinds of comparisons.
Right. I guess it really depends how people define "dirty checking". What I was trying to say is that at the end of the day you do diffing on some data structure: model in Angular and virtual Dom in React.
Loop vs. one pass is an important distinction, agreed. But when we bring Angular we should be noted that Angular 2 doesn't do those checks in a loop but does comparisons in one pass only.
My biggest complaints about angular aren't really the dirty checking system that it uses (though one of them is a side effect).
My biggest complaint is the weird dependency injection system that makes it difficult to track down where something comes from. It's better in 2, but still not as straight forward as React, where your child components are simply import/require statements that you can follow through to either an installed npm module, or a relative path. I try to avoid DI in JS wherever possible, it's almost never needed, and there are almost always simpler ways.
My second largest complaint on angular, is that I find that the way it handles state (though many are moving to a more react-like approach) leads to anything outside of the "angular way" being very complicated to work around. The fact that $scope.apply() is a thing kind of sums it up pretty nicely.
For most applications (we're not all building facebook level interactions), either comparison approach is not a performance issue in practice. What I do find is the flux/react way tends to have a bit more cognitive overhead to get started with, but additional features add less additional complexity than with angular.
A bit offtopic, but DI (via IoC container) is for managing runtime dependencies, which can get complex as an app grows. DI of the IoC container flavor is never necessary (I would argue that pure DI in itself is only a good thing though for clean separation of code), but one can say many things are not necessary - its existence is for making things simpler when working with complex apps. Without an IoC container, one has to manually pass around services to those requiring them if there is some complex runtime code - it sucks greatly when working with increasingly complex code, far more than using a system with an injector to manage the runtime constructs and to act as a fetcher that retrieves the necessary instance when requested. An example of the convoluted nature of handling dependencies without such a system is when one needs to test one service that say depends on another service that is x services removed in a dependency chain. In order to properly mock for testing, one has to potentially dig x levels deep to mock all relevant methods, instead of mocking the one service of interest.
It should also be noted that imports are orthogonal to the utility of DI. ES imports does not address the runtime dependency tree, and can certainly live alongside a tool such as DI - DI is for handling runtime dependency management, importing/exporting is more for handling initialization/compile time dependency management. Confusing the two is not understanding the problems they are meant to solve.
Angular 1's DI, while extremely convenient for testing, unfortunately does rely on a hacky implementation. Angular 2's DI system is extremely robust though, using the proposed ES7 decorator standard to more properly implement DI via IoC by using the services themselves (which are imported in) to fetch the appropriate instance - Angular 2's component system also makes it extremely easy to consume the injector with one line, or even creating new injectors to silo sectors of an application into runtime modules.
Angular 2 also espouses many of the ideas that React has pioneered in frontend web development - in fact, the Angular team would be quick to admit the faults present in Angular 1, which didn't have the benefit of the current state of HTML & JavaScript in the late '00s when it was conceived (ES module standard, annotations/decorators being a potential language feature, strong browser standards support across the major 4 browser vendors, etc.). Flux-like patterns can be easily implemented in Angular 2, and may see a surge in popularity given its popularity in the React ecosystem. Uni-directional data flow is at the core of Angular 2's component system.
What does one have to pass around? You can `require`/`import` service modules directly... for that matter, with a system like redux/react, you can easily pass anything needed via properties. You can create pretty complex applications without muddying where your services come from...
I've been following Angular2, and while much better than Angular1, still think react+redux as a workflow/render solution with separate state management reducers/handlers is a better workflow... especially as feature count goes up, because complexity doesn't climb as steeply as with Angular.