React.js: перенос одного компонента в другой

Многие языки шаблонов имеютслоты» или же "Уступать" операторы, которые позволяют сделать какое-то обращение контроля, чтобы обернуть один шаблон в другой.

Угловой имеетtransclude» вариант.

Rails имеетзаявление о доходности, Если бы в React.js был оператор yield, он бы выглядел так:

var Wrapper = React.createClass({
  render: function() {
    return (
      
        before
          
        after
      
    );
  }
});

var Main = React.createClass({
  render: function() {
    return (
      content
    );
  }
});

Желаемый вывод:


  before
    content
  after

Увы, React.js не делаетне иметь, Как определить компонент Wrapper для достижения того же результата?

Ответы на вопрос(3)

Решение Вопроса

Пытаться:

var Wrapper = React.createClass({
  render: function() {
    return (
      
        before
          {this.props.children}
        after
      
    );
  }
});

УвидетьНесколько компонентов: дети а такжеТип Детского реквизита в документах для получения дополнительной информации.

 Sebastien Lorber22 июл. 2015 г., 15:41
Или вы можете использовать компонент высшего порядка :)stackoverflow.com/a/31564812/82609
С помощьюchildren
const Wrapper = ({children}) => (
  
    header
    {children}
    footer
  
);

const App = ({name}) => Hello {name};

const WrappedApp = ({name}) => (
  
    
  
);

render(,node);

Это также известно какtransclusion в угловых.

children является специальной опорой в React и будет содержать то, что находится внутри вашего компонента »с тегами (здесь это внутриWrapperтак что этоchildren

Обратите внимание, что вы нет обязательно нужно использоватьchildren, который является уникальным для компонента, и вы можете использовать обычные реквизиты, если хотите, или смешивать реквизиты и потомки:

const AppLayout = ({header,footer,children}) => (
  
    {header}
    {children}
    {footer}
  
);

const appElement = (
  
    body
  
);

render(appElement,node);

Это просто и хорошо для многих случаев, и яЯ рекомендую это для большинства потребительских приложений.

сделать реквизит

Можно передать функции рендеринга компоненту, этот шаблон обычно называетсяrender propиchildren prop часто используется для обеспечения этого обратного вызова.

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

Встречный пример:

const Counter = () => (
  
    {(val, set) => (
       set(val + 1)}>  
        clicked {val} times
      
    )}
  
); 

Вы можете получить еще больше фантазии и даже предоставить объект


  {{
    loading: () => ...,
    success: (data) => {data.something},
    error: (e) => {e.message},
  }}

Обратите внимание, что вы нет обязательно нужно использоватьchildrenЭто вопрос вкуса / API.

 ...}
  renderSuccess={(data) => {data.something}}
  renderError={(e) => {e.message}}
/>

На сегодняшний день многие библиотеки используют реквизит рендеринга (контекст React, React-motion, Apollo ...), потому что люди склонны находить этот API проще, чем HOC 's.реагируют-вилка электропитания это коллекция простых компонентов render-prop.реагируют-принять поможет вам сделать композицию.

Компоненты высшего порядка (HOC).
const wrapHOC = (WrappedComponent) => {
  class Wrapper extends React.PureComponent {
    render() {
      return (
        
          header
          
          footer
        
      );
    }  
  }
  return Wrapper;
}

const App = ({name}) => Hello {name};

const WrappedApp = wrapHOC(App);

render(,node);

Компонент высшего порядка / HOC обычно это функция, которая принимает компонент и возвращает новый компонент.

Использование компонента высшего порядка может быть более производительным, чем использованиеchildren или жеrender propsпотому что обертка может иметь возможность замкнуть рендеринг на шаг впереди.shouldComponentUpdate

Здесь мы используемPureComponent, При повторном рендеринге приложения, еслиWrappedApp Название реквизита не меняется со временем, обертка имеет возможность сказать:Я ненужно рендерить, потому что реквизиты (собственно имя) такие же, как и раньше ", Сchildren решение на основе выше, даже если оберткаPureComponent, это не так, потому что дочерний элемент воссоздается каждый раз при визуализации родительского элемента, что означает, что оболочка, скорее всего, всегда будет повторно визуализироваться, даже если обернутый компонент является чистым. Eстьплагин Babel что может помочь смягчить это и обеспечить постоянныйchildren элемент со временем.

Заключение

Компоненты высшего порядка могут дать вам лучшую производительность. Это'Это не так сложно, но поначалу это выглядит недружелюбно.

Дон»после прочтения переведите всю кодовую базу в HOC. Просто помните, что на критических путях вашего приложения вы можете захотеть использовать HOC вместо оболочек времени выполнения по соображениям производительности, особенно если одна и та же оболочка используется много раз 'Стоит подумать о том, чтобы сделать это HOC.

Redux сначала использовал оболочку времени выполнения и позже переключился на HOCconnect(options)(Comp) по соображениям производительности (по умолчанию оболочка чистая и используетсяshouldComponentUpdate). Это отличная иллюстрация того, что я хотел выделить в этом ответе.

Обратите внимание, что если у компонента есть API рендеринга-пропа, поверх него обычно легко создать HOC, поэтому, если вы являетесь автором lib, вы должны сначала написать API-интерфейс рендеринга и в конечном итоге предложить версию HOC. Это то, что делает Аполлон компонент рендеринга иgraphql HOC с его помощью.

Лично я использую оба, но когда сомневаюсь, я предпочитаю HOC, потому что:

Это'более идиоматично их сочинять (compose(hoc1,hoc2)(Comp)) по сравнению с рендерингом реквизитаЭто может дать мне лучшие результаты.я знаком с этим стилем программирования

Я неНе стесняйтесь использовать / создавать HOC версии моих любимых инструментов:

РЕАКТContext.Consumer компнеустановленные-хSubscribeс помощьюgraphql HOC Аполлона вместоQuery оказывать опору

На мой взгляд, иногда реквизит рендеринга делает код более читабельным, иногда менее ... Я стараюсь использовать наиболее прагматичное решение в соответствии с имеющимися у меня ограничениями. Иногда читаемость важнее исполнения, иногда нет. Выбирай мудро и не делайНеукоснительно следуйте тенденции 2018 года по конвертации всего в рендер-реквизит.

 Mukesh Soni10 сент. 2015 г., 20:47
Этот подход также облегчает передачу подпрограммы дочернему компоненту (в данном случае Hello). Начиная с React 0.14. * И далее, единственный способ передать реквизиты дочерним компонентам - это использовать React.createClone, который может быть дорогим.
 Philipp09 авг. 2016 г., 00:03
Вопрос: ответ упоминает "лучшая производительность " - что я не делаюне понимаю: лучше по сравнению с каким другим решением?
 ColorWin03 янв. 2018 г., 04:45
Когда вы используете PureComponent, вы небольше не нужно возвращать функцию. Просто удалите одну функцию переноса:js const wrapHOC = (WrappedComponent) => { class Wrapper extends React.PureComponent { render() { return ( header footer ); } return Wrapper; }
 Sebastien Lorber03 янв. 2018 г., 10:41
спасибо @ColorWin, это была опечатка, я исправил это
 MacKentoch20 сент. 2018 г., 21:07
Спасибо! Как будто вы взяли слова из моего месяца, но выражаете их с большим талантом👍
 Sebastien Lorber09 авг. 2016 г., 10:49
HOC могут иметь лучшую производительность по сравнению с оболочками времени выполнения, так как они могут закорачивать рендеринг раньше.

В дополнение к Софиs ответ, я также нашел применение при отправке дочерних типов компонентов, делая что-то вроде этого:

var ListView = React.createClass({
    render: function() {
        var items = this.props.data.map(function(item) {
            return this.props.delegate({data:item});
        }.bind(this));
        return {items};
    }
});

var ItemDelegate = React.createClass({
    render: function() {
        return {this.props.data}
    }
});

var Wrapper = React.createClass({    
    render: function() {
        return 
    }
});
 krs03 янв. 2014 г., 14:39
Вы можете добавить любые реквизиты, которые вы хотите, к компоненту и назвать их как хотите, я использую this.props.delegate в строке 4, но с тем же успехом мог бы назвать его как-нибудь иначе.
 NVI03 янв. 2014 г., 11:08
Я нене видел никакой документации поdelegate, как ты нашел это?

Ваш ответ на вопрос