Як передати реагуючий компонент в інший реагуючий компонент, щоб перетворити вміст першого компонента?


215

Чи є спосіб передати один компонент в інший реагуючий компонент? Я хочу створити компонент реакції моделі та передати інший компонент реагування для того, щоб перетворити цей вміст.

Редагувати: Ось код reactJS, який ілюструє те, що я намагаюся зробити. 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'));

Відповіді:


197

Ви можете використовувати this.props.childrenдля відображення будь-яких дітей, що містять компонент:

const Wrap = ({ children }) => <div>{children}</div>

export default () => <Wrap><h1>Hello word</h1></Wrap>

4
Я би використав цю відповідь. this.props.childrenє частиною API компонента і, як очікується, буде використовуватися таким чином. У прикладах команди React використовується така методика, як при передачі реквізиту та при розмові про єдину дитину .
Росс Аллен

З мого коментаря нижче: передаючи його як опору, ви навіть можете дати йому ім'я та використовувати propTypes для введення перевірки.
returnneax

1
@AndrewAllbright: Ваш приклад не передавав жодних дітей. Це працює: codepen.io/ssorallen/pen/Dyjmk
Росс Аллен

І в разі , якщо ви тоді хочете отримати DOM Nodes дітей: stackoverflow.com/questions/29568721 / ...
ericsoco

124

Зверніть увагу , я надав відповідь глибший тут

Обгортка під час виконання:

Це самий ідіоматичний спосіб.

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's 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);

Це може призвести до (мало) кращих характеристик, оскільки компонент обгортки може коротко замикати візуалізацію на один крок вперед з shouldComponentUpdate, тоді як у випадку з обгорткою часу виконання, підказки для дітей, ймовірно, завжди будуть іншими ReactElement і викликати повторні візуалізації навіть якщо ваші компоненти поширюють PureComponent.

Зауважте, що connectRedux раніше був обгорткою виконання, але він був змінений на HOC, оскільки він дозволяє уникнути марних повторних візуалізацій, якщо ви використовуєте цю pureопцію (що відповідає дійсності за замовчуванням)

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


Зауважте, що при використанні функціональних компонентів, як вище, версія HOC не забезпечує корисної оптимізації, оскільки функціональні компоненти без стану не реалізуються shouldComponentUpdate

Більше пояснень тут: https://stackoverflow.com/a/31564812/82609


29
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} />

Це було б правильно, якби ... React 15.x забороняє повертати компонент з декількома вузлами. React 16 (він же React Fiber) дозволить отримати декілька вузлів. Ось виправлення для вашого зразка коду: const ParentComponent = (props) => ({props.childComponent}); імпортувати MyComponent з //..., коли-небудь const myComponent = <MyComponent /> // передавати як опора <ParentComponent childComponent = {myComponent} />
Ендрю Олбрайт

13

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);

13

Ви можете передати це як звичайну опору: 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>

9

я вважаю за краще використовувати вбудований 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> 

5

Ви можете передати компонент через. реквізит і візуалізувати його за допомогою інтерполяції.

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

Потім ви перейдете до propдзвінка child, який би був компонентом React.


1
Це призведе до передачі компонентів через атрибути, а не як діти. Якщо ви використовуєте, this.props.childrenяк пропонується в іншій відповіді, ви можете записувати дітей як діти замість attrs.
Росс Аллен

1
@ssorallen ви не сказали, чому краще в будь-якому випадку ... Передаючи його як опору, ви навіть можете дати йому ім'я та використовувати propTypes для перевірки типу.
returnneax

1
Кожен елемент, який ви використовуєте в JSX, є лише компонентом. Якби вони використовували такий підхід, ви не змогли б написати навіть свій короткий приклад. Це стане <div child={this.props.child />.
Росс Аллен

1
Ознайомтеся з версією JavaScript (у що перетворює JSX): jsfiddle.net/ssorallen/kvrxcqv8/2 . React.DOM.div, як і всі основні компоненти, використовує childrenмасив. Подивіться, як він використовується у вашому Helloкомпоненті, він вже використовує декілька дітей.
Росс Аллен

20
Мінусом продовження дискусії у чаті є те, що вони не отримують архіву для майбутніх читачів.
ultrafez

3

Пізно в грі, але ось потужний шаблон 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}/>);

1

Власне, ваше питання полягає в тому, як написати компонент вищого порядку (HOC). Основна мета використання HOC - запобігання скріплення копій. Ви можете написати свій HOC як суто функціональний компонент або як клас, ось приклад:

    class Child extends Component {
    render() {
        return (
            <div>
                Child
            </div>
        );
    }
}

Якщо ви хочете записати свій батьківський компонент як компонент на основі класу:

    class Parent extends Component {
    render() {
        return (
            <div>
                {this.props.children}
            </div>
        );
    }
}

Якщо ви хочете записати батьків як функціональний компонент:

    const Parent=props=>{
    return(
        <div>
            {props.children}
        </div>
    )
}

0

Ось приклад компонента реакції батьківського списку, а реквізити містять елемент реагування. У цьому випадку передається лише один компонент реагування Link (як видно з візуалізації dom).

class Link extends React.Component {
  constructor(props){
    super(props);
  }
  render(){
    return (
      <div>
        <p>{this.props.name}</p>
      </div>
     );
  }
}
class List extends React.Component {
  render(){
   return(
    <div>
       {this.props.element}
       {this.props.element}
    </div>
   );
  }
}

ReactDOM.render(
  <List element = {<Link name = "working"/>}/>,
  document.getElementById('root')
);

0

Так, ви можете зробити це за допомогою реквізиту, ви можете передавати дані компонента як об'єкт, як реквізит, а потім всередині компонента ви можете імпортувати інший компонент і динамічно зв'язувати з даними prpps. читати більше про компонент реагування


1
чи можете ви детально розібратися з кодом за посиланням, яке ви розмістили
Неллес
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.