Шаблоны проектирования компонентов React — объединение компонентов
Шаблон проектирования компонентов React — поставщик-потребитель
При написании бизнеса нам часто нужно абстрагировать некоторую часто используемую логику, но в дополнение к абстрактной логике компонентов высокого порядка RenderProps также является лучшим методом.
RenderProps, как следует из названия, отображает свойства компонента. На самом деле, пусть пропсы компонента получают функцию, а функция будет рендерить контент. общая логика Он абстрагируется внутри компонента, а затем вызывается функция (функция, которая отображает содержимое в свойствах) в соответствии с бизнес-логикой, чтобы достичь цели повторного использования логики.
Простая реализация
Давайте сначала рассмотрим реализацию простейшего паттерна RenderProps:
const RenderProps = props => <>
{props.children(props)}
</>
Здесь дочерний компонент компонента RenderProps — это функцияprops.children(props), а props.children возвращает элементы пользовательского интерфейса.
Используемый код выглядит следующим образом:
<RenderProps>
{() => <>Hello RenderProps</>}
</RenderProps>
Какая польза от вышеизложенного без какой-либо обработки бизнес-логики? Мы можем представить, что можем использовать код в компоненте RenderProps для управления возвращаемым результатом. Возьмем в качестве примера наиболее распространенную логику входа пользователя, я надеюсь, вы сможете увидеть содержимое после входа в систему, в противном случае, пожалуйста, войдите, чтобы отобразить:
const Auth = props => {
const userName = getUserName()
if (userName) {
const allProps = {userName, ...props}
return <>
{props.children(allProps)}
</>
} else {
return <>请登录</>
}
}
<Auth>
{({userName}) => <>Hello!{userName}</>}
</Auth>
props.children(allProps)Это эквивалентно вложенному компоненту Auth({userName}) => <>Hello!{userName}</>
В приведенном выше примере, если пользователь уже вошел в систему, getUserName возвращает имя пользователя, в противном случае возвращает значение null. Таким образом, мы можем определить, что возвращать. Конечно, userName передается через renderProps, что является усовершенствованием компонента Auth.
Имя функции может быть не только дочерним
В общем случае props.children являются конкретными экземплярами компонентов, но приведенная выше реализация основана на функциях как дочерних компонентах (children(props)), который вызывается для возврата к пользовательскому интерфейсу.
Точно так же можно вызвать любую функцию из реквизита. Или возьмем приведенную выше логику в качестве примера:
const Auth = props => {
const userName = 'Mike'
if (userName) {
const allProps = { userName, ...props }
return <>{props.login(allProps)}</>
} else {
return <>
{props.noLogin(props)}
</>
}
}
Способ применения следующий:
<Auth
login={({userName}) => <h1>Hello {userName}</h1>}
noLogin={() => <h1>please login</h1>}
/>
Здесь свойства компонента Auth получают две функции:логин (указывает на то, что вы вошли в систему),noLogin (стол не авторизован), Внутри компонента Auth, какой компонент отображается, оценивая, следует ли войти в систему или нет.
Суммировать
Как метод абстрагирования общей логики, сам render-props также сталкивается с проблемой вложенности в слои, такие как компоненты более высокого порядка.
<GrandFather>
{Props => {
<Father>
{props => {
<Son {...props} />;
}}
</Father>;
}}
</GrandFather>
Но в отличие от компонентов более высокого порядка, поскольку функции рендерятся (компоненты высокого порядка рендерят компоненты), это дает возможность использовать compose. Напримерreact-powerplugin.
import { compose } from 'react-powerplug'
const ComposeComponent = compose(
<GrandFather />,
<Father />
)
<ComposeComponent>
{props => {
<Son {...props} />;
}}
<ComposeComponent/>
а такжеEpitathДля решения этой проблемы также предусмотрен новый режим. Эта часть развития темы - отдельная тема, тоже шарю.