Решил самостоятельно изучить более детально реакт, потому что сижу очень давно на ангуляре, и столкнулся с тем что не понимаю как правильно написать компонент. Исходные условия такие:
Представим что я делаю компонент dropdown. У него есть выпадающее меню.
Бест практис - делать глупый компонент, который занимается только рендерингом по пропсам, с этим проблем нет, написал так что показ/скрытие выпадашки зависит от пропса. А вот далее проблема - надо управлять состоянием показа меню, значит делаем обёртку в виде умного компонента, внутри которого есть метод-колбек, который дергается при клике на тайтл дропдауна и меняет стейт. В итоге получается такой себе standalone дропдаун, который можно подключать куда угодно и он даже реализован по канонам.
Далее я подумал о том, а что если мы захотим при инициализации дропдаун сразу открыть, так что надо сделать компонент одновременно и управляемым и нет - наткнулся на "uncontrollable" пакет, подключил, стало ещё более круто - можно юзать либо стендалон компонент, который сам следит за своим состоянием, либо если надо управлять из того место где мы его подключаем, мы передаём через пропсы управляющие данные и рулим дропдауном "сверху".
Тут то можно было и закончить, но довольно часто требуются такие юзкейсы: Дропдаун висит где-то в одной части страницы, а кнопка управления дропдауном в другой её части, и единственное что у них общего - это рут-элемент в паре прыжков "наверх" от каждого из них. При этом дропдаун должен быть uncontrollable, т.е. хранить в себе свой стейт и независимо переключать показ своего меню, НО, при клике на вышеобозначенную кнопку он должен, например, раскрыться, независимо от своего состояния (рскрыт/скрыт).
И как это реализовать я не понимаю. если делать контроллируемый компонент извне, то придётся писать логику, а это значит что другие компоненты будут о нём много знать. Из того с чем я работал, я бы мог предложить две реализации подобного:
- У дропдаун компонента делается публичное апи с методами show() и hide(), и через пропсы принимается колбек, в который отдаётся объект с апи.
- реакт-way, используется Ref, через который дергается нужный метод. Минус этого подхода - через реф отдаётся вся подноготная компонента с потрохами, да и использование рефов в таком контексте мне кажется очень бэд практис
Интуиция мне подсказывает что есть какое-то очень простое решение.
Знаю что подобное могло бы решиться редаксом, но я хотел бы узнать как это написать на более-менее чистом реакте, и хочется чтобы это решение было именно стендалон, т.е. чтобы можно было взять этот компонент и добавить в другой проект, в котором может не оказаться MobX или Redux. Опять же, интересно такое решение которое в более менее крупной компании на код ревью не завернут со словами "да у вас же костыль", хочется энтерпрайзное, то что вы каждый день пишете на работе.
Если есть какие-то статьи на подобную тему, буду очень рад ссылкам.