Что такое реквизит для рендеринга? Согласно официальному определению реакции:

относится к технике совместного использования кода между компонентами React с использованием реквизита, значением которого является функция.

Другими словами, компоненты родительского компонента или компонента-контейнера могут получить доступ к состояниям или функциям дочернего компонента без необходимости передавать туда и обратно реквизиты.

Это очень полезно, когда мы знаем, что есть компонент с рекурсивной или итеративной логикой, который нужно использовать в нескольких местах.

Итак, как мы можем инкапсулировать это поведение, чтобы мы могли легко поделиться им с родительскими компонентами?

Давайте попробуем выполнить рефакторинг от шаблона State Hoisting к шаблону Render Props.

(«поднятие состояния» осуществляется путем передачи обратного вызова из компонента-контейнера в дочерний компонент.)

Пример 1

Допустим, есть компонент Input, который получает обратный вызов от компонента InputContainer и вызывает события. С помощью обратного вызова состояние поднимается в контейнер, в котором оно обновляет локальное состояние.

const Input = ({ onChange }) => (
  <input onChange={e => onChange(e.target.value)} />
);
class InputContainer extends Component {
 state = { name: "" };
 render() {
   return (
     <>
      <Input onChange={newName => this.setState({ name: newName })} />
      <p>{this.state.name}</p>
     </>
   );
 }
}

— — — коды рефакторинга для Render Props ›››

class Input extends Component {
 state = {
   name: 'Alice',
 }
render() {
  return (
   <>
    <input onChange={e => this.setState({ name: e.target.value})} /
     {this.props.render(this.state)}
   </>
  );
 }
}
function InputContainer() {
 return <Input render={({ name }) => <p>{name}</p>} />
}

Здесь произошло то, что состояние теперь контролируется внутри Input, а не с помощью InputContainer. Но InputContainer по-прежнему может получить доступ к состоянию с реквизитами рендеринга.

Это не выглядит впечатляюще. пока что. Но всякий раз, когда вы хотите использовать компонент ввода в другом месте, вам больше не нужно повторять такие коды, как this.setState… больше!

Вы также можете преобразовать коды в шаблон FaaC (Function-as-a-Child).

— — — коды рефакторинга для Render Props (шаблон FaaC)›››

class Input extends Component {
state = {
   name: 'Alice',
 }
render() {
  return (
   <>
    <input onChange={e => this.setState({ name: e.target.value})} /
     {this.props.children(this.state)}
   </>
  );
 }
}
function InputContainer() {
 return <Input>{({ name }) => <p>{name}</p>}</Input>
}

Это в конечном счете одно и то же. Но лично шаблон FaaC выглядит намного чище.

Пример 2

Вы также можете отправить функцию в качестве реквизита рендеринга. Это также очень полезно в случае, когда вам не нужно знать состояние потребителя, а нужно знать только функцию, контролирующую состояние.

Например, здесь у нас есть модальный компонент, и мы хотим управлять состоянием isVisible из родителя, но нам не обязательно это состояние.

function ModalContainer(){
return(
 <Modal>
 {({ showModal }) => (
  <CloseButton onClick={(e) => {
   e.stopPropagation();
   e.preventDefault();
   showModal();
  }} />
 )}
 </Modal>
)
}
class Modal extends Component {
 state = { visible: false };
 showModal = () => { this.setState({ visible: true }) };
 hideModal = () => { this.setState({ visible: false }) };
 render() {
 const { visible } = this.state;
 return (
<>
 <div className={classnames('Modal', {
   'Modal-visible': visible
 })}>
 ....{modal content}
 <Button handleClick={this.hideModal}>
  Cancel
 </Button>
</div>
{children({ showModal: this.showModal })}
</>
 );
}

Плюсы и минусы

Плюсы!

  • Это очень полезно, когда мы знаем, что есть компонент с рекурсивной или итеративной логикой, потому что мы можем инкапсулировать его в 1 компонент и читать из разных мест.
  • очень ясно, какой компонент вызывается, и состояние изолировано.
  • никаких коллизий имен, как у вас будет с HOC

Недостатки:

  • не так аккуратно в JSX, так как его нужно обернуть выражением.
  • поскольку его нужно обернуть, вы не можете использовать реквизиты рендеринга, когда хотите, чтобы контейнер и потребитель находились в двух разных местах.

Использованная литература:

https://cdb.reacttraining.com/use-a-render-prop-50de598f11ce





Реквизиты рендеринга — React
Термин «реквизит рендеринга
относится к методу совместного использования кода между компонентами React с использованием реквизита, значением которого является…reactjs.org »