Digamos que estoy obteniendo algunas imágenes de una API en el componente de la aplicación.
Luego quiero pasarlo al componente responsable de renderizar imágenes. Pero este componente no es un elemento secundario directo del componente de la aplicación. Es el hijo de un hijo directo del componente de la aplicación.
Así es como pasaría la matriz de imágenes al componente de imagen, pero creo que podría no ser el mejor enfoque.
Pero, ¿qué pasaría si esta jerarquía se vuelve más compleja, incluso solo por un componente más? 
Intuitivamente, puede que no sea lo mejor.
Entonces, ¿cuál sería la mejor manera de pasar la matriz de imágenes al componente de imagen, si hay muchos otros elementos secundarios entre ellos?
El problema generalmente se llama Prop Drilling en el mundo de React: https://kentcdodds.com/blog/prop-drilling
Algunas opciones:
Pasar accesorios puede no ser tan malo. Si la aplicación es pequeña, es una opción muy modular y fácil de probar. Puede reducir la verbosidad usando prop spread: <Comp {...props} /> y manteniendo similares las interfaces de sus componentes. (A muchas personas no les gusta la difusión de accesorios, ya que puede pasar involuntariamente accesorios no admitidos, pero si usa TypeScript, el compilador lo detectará).
Puede usar un contexto de reacción: https://reactjs.org/docs/context.html (como otra mención en los comentarios). Sin embargo, vigile cómo se definen sus objetos de contexto (manténgalos pequeños). React volverá a renderizar todos los niños usando el contexto cuando el valor cambie, no es lo suficientemente inteligente como para detectar automáticamente los cambios en el nivel de propiedad. Frameworks como Redux o Zustand usan otros mecanismos para permitir un control granular del estado compartido (verá ejemplos de un gancho useSelector ).
También puede echar un vistazo a un marco de gestión de estado (Zustand es mi favorito, pero Redux es más popular). Sin embargo, puede ser una exageración para las cosas pequeñas.
Mi elección personal es comenzar con la perforación de apoyo, es más fácil modularizar y probar la unidad. Luego, puede pensar en su aplicación en capas: las capas superiores dependen de un contexto (o un marco de estado) y las capas inferiores reciben propiedades. Eso ayuda cuando desea refactorizar y mover componentes reutilizables a otros proyectos.