Как передать компонент реакции в другой компонент реакции, чтобы включить содержимое первого компонента?

154

Есть ли способ передать один компонент в другой компонент реакции? Я хочу создать компонент реакции модели и передать в другой компонент реакции, чтобы перекрыть этот контент.

Изменить: Вот код, который я пытаюсь сделать. http://codepen.io/aallbrig/pen/bEhjo

HTML

<div id="my-component">
    <p>Hi!</p>
</div>

ReactJS

/**@jsx React.DOM*/

var BasicTransclusion = React.createClass({
  render: function() {
    // Below 'Added title' should be the child content of <p>Hi!</p>
    return (
      <div>
        <p> Added title </p>
        {this.props.children}
      </div>
    )
  }
});

React.renderComponent(BasicTransclusion(), document.getElementById('my-component'));
Теги:

8 ответов

153
Лучший ответ

Вы можете использовать this.props.children для рендеринга любых дочерних элементов, содержащихся в компоненте:

const Wrap = props => <div>{props.children}</div>

export default () => <Wrap><h1>Hello word</h1></Wrap>
  • 2
    Я бы использовал этот ответ. this.props.children является частью API компонента и, как ожидается, будет использоваться таким образом. Примеры команды React используют эту технику, например, при передаче реквизита и при разговоре об одном ребенке .
  • 0
    Из моего комментария ниже: передавая его как реквизит, вы даже можете дать ему имя и использовать propTypes для проверки типа.
Показать ещё 2 комментария
92

Примечание. Я предоставил более подробный ответ здесь

Обертка времени выполнения:

Это самый идиоматический путь.

const Wrapper = ({children}) => (
  <div>
    <div>header</div>
    <div>{children}</div>
    <div>footer</div>
  </div>
);

const App = () => <div>Hello</div>;

const WrappedApp = () => (
  <Wrapper>
    <App/>
  </Wrapper>
);

Обратите внимание, что children является "специальной опорой" в React, а пример выше - синтаксический сахар и (почти) эквивалентен <Wrapper children={<App/>}/>


Оболочка инициализации /HOC

Вы можете использовать компонент более высокого порядка (HOC). Недавно они были добавлены в официальный официальный документ.

// Signature may look fancy but it just 
// a function that takes a component and returns a new component
const wrapHOC = (WrappedComponent) => (props) => (
  <div>
    <div>header</div>
    <div><WrappedComponent {...props}/></div>
    <div>footer</div>
  </div>
)

const App = () => <div>Hello</div>;

const WrappedApp = wrapHOC(App);

Это может привести к (небольшим) лучшим результатам, потому что компонент-обертка может коротко отстроить рендеринг на один шаг вперед с помощью mustComponentUpdate, в то время как в случае оболочки времени выполнения поддержка детей, вероятно, всегда будет другим ReactElement и вызовет re-render, даже если ваши компоненты расширяют PureComponent.

Обратите внимание, что connect для Redux использовался как оболочка среды выполнения, но был изменен на HOC, поскольку он позволяет избежать ненужных повторных рендеров, если вы используете опцию pure (которая по умолчанию истинна)

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


Обратите внимание, что при использовании таких функциональных компонентов, как выше, HOC-версия не обеспечивает никакой полезной оптимизации, поскольку функциональные компоненты без состояния не реализуют shouldComponentUpdate

Дополнительные пояснения здесь: https://stackoverflow.com/questions/20851533/react-js-wrapping-one-component-into-another

17
const ParentComponent = (props) => {
  return(
    {props.childComponent}
    //...additional JSX...
  )
}

//import component
import MyComponent from //...where ever

//place in var
const myComponent = <MyComponent />

//pass as prop
<ParentComponent childComponent={myComponent} />
  • 0
    Это было бы правильно, если бы это было ... React 15.x не позволяет вам возвращать многоузловой компонент. React 16 (он же React Fiber) позволит использовать несколько узлов. Вот исправление для вашего примера кода: const ParentComponent = (props) => ({props.childComponent}); импортировать MyComponent из //... везде когда-либо const myComponent = <MyComponent /> // передать как prop <ParentComponent childComponent = {myComponent} />
  • 0
    Это работает, есть ли причина не использовать его?
10

Facebook рекомендует использовать компонент без гражданства Источник: https://facebook.github.io/react/docs/reusable-components.html

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

function Label(props){
    return <span>{props.label}</span>;
}

function Hello(props){
    return <div>{props.label}{props.name}</div>;
}

var hello = Hello({name:"Joe", label:Label({label:"I am "})});

ReactDOM.render(hello,mountNode);
7

Я предпочитаю использовать встроенный API React:

import React, {cloneElement, Component} from "react";
import PropTypes from "prop-types";

export class Test extends Component {
  render() {
    const {children, wrapper} = this.props;
    return (
      cloneElement(wrapper, {
        ...wrapper.props,
        children
      })
    );
  }
}

Test.propTypes = {
  wrapper: PropTypes.element,
  // ... other props
};

Test.defaultProps = {
  wrapper: <div/>,
  // ... other props
};

то вы можете заменить div обертки тем, что вы хотите:

<Test wrapper={<span className="LOL"/>}>
  <div>child1</div>
  <div>child2</div>
</Test> 
3

Вы можете передать его как обычный реквизит: foo={<ComponentOne/>}

Например:

const ComponentOne = () => <div>Hello world!</div>
const ComponentTwo = () => (
  <div>
    <div>Hola el mundo!</div>
    <ComponentThree foo={<ComponentOne />} />
  </div>
)
const ComponentThree = ({ foo }) => <div>{foo}</div>
3

Вы можете передать компонент через. реквизит и сделать его с интерполяцией.

var DivWrapper = React.createClass({
    render: function() {
        return <div>{ this.props.child }</div>;
    }
});

Затем вы передали бы prop, называемый child, который будет компонентом React.

  • 1
    Это приведет к передаче компонентов через атрибуты, а не как дочерние элементы. Если вы используете this.props.children как предложено в другом ответе, вы можете написать детей как детей, а не attrs.
  • 1
    @ssorallen вы не сказали, почему кто-то лучше ... Передавая его как реквизит, вы даже можете дать ему имя и использовать propTypes для проверки типа.
Показать ещё 8 комментариев
0

Поздно к игре, но здесь мощный шаблон HOC для переопределения компонента, предоставляя его в качестве опоры. Это просто и элегантно.

Предположим, что MyComponent отображает вымышленный компонент A но вы хотите разрешить пользовательское переопределение A, в этом примере B, которое оборачивает A в <div>...</div> а также добавляет "!" к текстовой опоре:

import A from 'fictional-tooltip';

const MyComponent = props => (
  <props.A text="World">Hello</props.A>
);
MyComponent.defaultProps = { A };

const B = props => (
  <div><A {...props} text={props.text + '!'}></div>
);

ReactDOM.render(<MyComponent A={B}/>);

Ещё вопросы

Сообщество Overcoder
Наверх
Меню