function _flush(rootNode: AnimatedValue): void {
  const animatedStyles = new Set();
  function findAnimatedStyles(node) {
    if (typeof node.update === 'function') {
      animatedStyles.add(node);
    } else {
      node.__getChildren().forEach(findAnimatedStyles);
    }
  }
  findAnimatedStyles(rootNode);
  /* $FlowFixMe */
  animatedStyles.forEach(animatedStyle => animatedStyle.update());
}
Animated works by building a directed acyclic graph of dependencies
transparently when you render your Animated components.

              new Animated.Value(0)
    .interpolate()        .interpolate()    new Animated.Value(1)
        opacity               translateY      scale
         style                         transform
        View#234                         style
                                        View#123

A) Top Down phase
When an Animated.Value is updated, we recursively go down through this
graph in order to find leaf nodes: the views that we flag as needing
an update.

B) Bottom Up phase
When a view is flagged as needing an update, we recursively go back up
in order to build the new value that it needs. The reason why we need
this two-phases process is to deal with composite props such as
transform which can receive values from multiple parents.