Шаблоны проектирования компонентов React — Render-props

React.js

Шаблоны проектирования компонентов 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Для решения этой проблемы также предусмотрен новый режим. Эта часть развития темы - отдельная тема, тоже шарю.