способ #1
родительский компонент явно знает что нужно дочернему компоненту и тогда родительский компонент явно передаёт нужные значения через props
Один из главных минусов: в каждом родительском компоненте нужно учитывать требования всех дочерних компонентов на всех нижележащих уровнях
способ #2
родительский компонент предполагает что дочерний компонент будет использовать что-то из его props и state (т.е. из props и state родительского компонента). Поэтому родительский компонент явно передаёт свои state и props дочернему элементу с помощью props
Минус #1 - см. способ #1
Минус #2 - состояние данного родительского компонента становится общедоступным. Что не всегда хорошо
способ #3
данные которые нужны для разных компонентов выносятся в глобальную область видимости (redux, flux, mobx и т.д.).
В этом случае родительский компонент обновляет какую-то часть общедоступных данных.
Другие компоненты, которые заинтересованы в этих данных, подписываются на уведомления об изменениях этих данных
Минус - дополнительный уровень абстракции
Но решает недостатки предыдущих вариантов
Что лучше... Зависит от ситуации