Cách chuyển đạo cụ cho {this.props.children}

973
plus- 2015-09-03 22:47.

Tôi đang cố gắng tìm cách thích hợp để xác định một số thành phần có thể được sử dụng theo cách chung chung:

<Parent>
  <Child value="1">
  <Child value="2">
</Parent>

Tất nhiên, có một logic đang diễn ra để hiển thị giữa các thành phần cha và con, bạn có thể tưởng tượng <select><option>lấy ví dụ về logic này.

Đây là một triển khai giả cho mục đích của câu hỏi:

var Parent = React.createClass({
  doSomething: function(value) {
  },
  render: function() {
    return (<div>{this.props.children}</div>);
  }
});

var Child = React.createClass({
  onClick: function() {
    this.props.doSomething(this.props.value); // doSomething is undefined
  },
  render: function() {
    return (<div onClick={this.onClick}></div>);
  }
});

Câu hỏi đặt ra là bất cứ khi nào bạn sử dụng {this.props.children}để định nghĩa một thành phần trình bao bọc, làm thế nào để bạn chuyển một số thuộc tính cho tất cả các thuộc tính con của nó?

26 answers

1043
Dominic 2015-09-03 23:17.

Nhân bản trẻ em bằng các đạo cụ mới

Bạn có thể sử dụng React.Childrenđể lặp lại các phần tử con, sau đó sao chép từng phần tử bằng các đạo cụ mới (hợp nhất nông) bằng cách sử dụng React.cloneElement. Ví dụ:

const Child = ({ doSomething, value }) => (
    <button onClick={() => doSomething(value)}>Click Me</button>
);

class Parent extends React.Component{
    doSomething = value => {
        console.log("doSomething called by child with value:", value);
    }

    render() {
        const childrenWithProps = React.Children.map(this.props.children, child => {
            // checking isValidElement is the safe way and avoids a typescript error too
            if (React.isValidElement(child)) {
                return React.cloneElement(child, { doSomething: this.doSomething });
            }
            return child;
        });

        return <div>{childrenWithProps}</div>;
    }
}

function App() {
    return (
        <Parent>
            <Child value={1} />
            <Child value={2} />
        </Parent>
    );
}

ReactDOM.render(<App />, document.getElementById("container"));
<script src="https://unpkg.com/[email protected]/umd/react.production.min.js"></script>
<script src="https://unpkg.com/[email protected]/umd/react-dom.production.min.js"></script>
<div id="container"></div>

Gọi trẻ em như một chức năng

Ngoài ra, bạn có thể chuyển đạo cụ cho trẻ em bằng các đạo cụ kết xuất . Trong cách tiếp cận này, các hàm con (có thể là childrenhoặc bất kỳ tên prop nào khác) là một hàm có thể chấp nhận bất kỳ đối số nào bạn muốn truyền và trả về các hàm con:

const Child = ({ doSomething, value }) => (
    <button onClick={() => doSomething(value)}>Click Me</button>
);

class Parent extends React.Component{
    doSomething = value => {
        console.log("doSomething called by child with value:", value);
    }

    render(){
        // note that children is called as a function and we can pass args to it
        return <div>{this.props.children(this.doSomething)}</div>
    }
};

function App(){
    return (
        <Parent>
            {doSomething => (
                <React.Fragment>
                    <Child doSomething={doSomething} value={1} />
                    <Child doSomething={doSomething} value={2} />
                </React.Fragment>
            )}
        </Parent>
    );
}

ReactDOM.render(<App />, document.getElementById("container"));
<script src="https://unpkg.com/[email protected]/umd/react.production.min.js"></script>
<script src="https://unpkg.com/[email protected]/umd/react-dom.production.min.js"></script>
<div id="container"></div>

Thay vì <React.Fragment>hoặc đơn giản là <>bạn cũng có thể trả về một mảng nếu bạn muốn.

419
Andres F Garcia 2016-01-31 03:20.

Để có cách làm gọn gàng hơn một chút, hãy thử:

<div>
    {React.cloneElement(this.props.children, { loggedIn: this.state.loggedIn })}
</div>

Chỉnh sửa: Để sử dụng với nhiều con riêng lẻ (bản thân con phải là một thành phần), bạn có thể thực hiện. Đã thử nghiệm trong 16.8.6

<div>
    {React.cloneElement(props.children[0], { loggedIn: true, testingTwo: true })}
    {React.cloneElement(props.children[1], { loggedIn: true, testProp: false })}
</div>
84
7puns 2016-06-07 04:42.

Thử đi

<div>{React.cloneElement(this.props.children, {...this.props})}</div>

Nó hoạt động với tôi bằng cách sử dụng react-15.1.

73
Lyubomir 2016-09-09 12:45.

Truyền đạo cụ cho trẻ chỉ đạo.

Xem tất cả các câu trả lời khác

Chuyển dữ liệu chung, toàn cục qua cây thành phần thông qua ngữ cảnh

Ngữ cảnh được thiết kế để chia sẻ dữ liệu có thể được coi là "toàn cầu" cho một cây các thành phần React, chẳng hạn như người dùng, chủ đề hoặc ngôn ngữ ưa thích hiện tại đã được xác thực. 1

Tuyên bố từ chối trách nhiệm: Đây là câu trả lời được cập nhật, câu trả lời trước đã sử dụng API ngữ cảnh cũ

Nó dựa trên nguyên tắc Người tiêu dùng / Cung cấp. Đầu tiên, tạo bối cảnh của bạn

const { Provider, Consumer } = React.createContext(defaultValue);

Sau đó sử dụng qua

<Provider value={/* some value */}>
  {children} /* potential consumers */
<Provider />

<Consumer>
  {value => /* render something based on the context value */}
</Consumer>

Tất cả Người tiêu dùng là con cháu của Nhà cung cấp sẽ hiển thị lại bất cứ khi nào giá trị của Nhà cung cấp thay đổi. Việc truyền từ Nhà cung cấp đến Người tiêu dùng con cháu của nó không phải tuân theo phương thức shouldComponentUpdate, vì vậy Người tiêu dùng được cập nhật ngay cả khi một thành phần tổ tiên không cập nhật. 1

Ví dụ đầy đủ, mã bán giả.

import React from 'react';

const { Provider, Consumer } = React.createContext({ color: 'white' });

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      value: { color: 'black' },
    };
  }

  render() {
    return (
      <Provider value={this.state.value}>
        <Toolbar />
      </Provider>
    );
  }
}

class Toolbar extends React.Component {
  render() {
    return ( 
      <div>
        <p> Consumer can be arbitrary levels deep </p>
        <Consumer> 
          {value => <p> The toolbar will be in color {value.color} </p>}
        </Consumer>
      </div>
    );
  }
}

1 https://facebook.github.io/react/docs/context.html

51
Kenneth Truong 2018-04-09 20:02.

Chuyển đạo cụ cho trẻ em lồng nhau

Với bản cập nhật lên React 16.6, giờ đây bạn có thể sử dụng React.createContextcontextType .

import * as React from 'react';

// React.createContext accepts a defaultValue as the first param
const MyContext = React.createContext(); 

class Parent extends React.Component {
  doSomething = (value) => {
    // Do something here with value
  };

  render() {
    return (
       <MyContext.Provider value={{ doSomething: this.doSomething }}>
         {this.props.children}
       </MyContext.Provider>
    );
  }
}

class Child extends React.Component {
  static contextType = MyContext;

  onClick = () => {
    this.context.doSomething(this.props.value);
  };      

  render() {
    return (
      <div onClick={this.onClick}>{this.props.value}</div>
    );
  }
}


// Example of using Parent and Child

import * as React from 'react';

class SomeComponent extends React.Component {

  render() {
    return (
      <Parent>
        <Child value={1} />
        <Child value={2} />
      </Parent>
    );
  }
}

React.createContext tỏa sáng trong trường hợp React.cloneElement không thể xử lý các thành phần lồng nhau

class SomeComponent extends React.Component {

  render() {
    return (
      <Parent>
        <Child value={1} />
        <SomeOtherComp><Child value={2} /></SomeOtherComp>
      </Parent>
    );
  }
}
24
Alireza 2017-06-12 21:03.

Bạn có thể sử dụng React.cloneElement, tốt hơn là bạn nên biết nó hoạt động như thế nào trước khi bắt đầu sử dụng nó trong ứng dụng của mình. Nó được giới thiệu trong React v0.13, hãy đọc để biết thêm thông tin, vì vậy một cái gì đó cùng với công việc này cho bạn:

<div>{React.cloneElement(this.props.children, {...this.props})}</div>

Vì vậy, hãy mang theo các dòng từ tài liệu React để bạn hiểu cách tất cả hoạt động và cách bạn có thể sử dụng chúng:

Trong React v0.13 RC2, chúng tôi sẽ giới thiệu một API mới, tương tự như React.addons.cloneWithProps, với chữ ký này:

React.cloneElement(element, props, ...children);

Không giống như cloneWithProps, chức năng mới này không có bất kỳ hành vi tích hợp ma thuật nào để hợp nhất style và className vì lý do tương tự như chúng tôi không có tính năng đó từ transferPropsTo. Không ai chắc chắn chính xác danh sách đầy đủ của những điều kỳ diệu là gì, điều này gây khó khăn cho việc suy luận về mã và khó sử dụng lại khi phong cách có một chữ ký khác (ví dụ như trong React Native sắp tới).

React.cloneElement gần như tương đương với:

<element.type {...element.props} {...props}>{children}</element.type>

Tuy nhiên, không giống như JSX và cloneWithProps, nó cũng bảo tồn các ref. Điều này có nghĩa là nếu bạn có được một đứa trẻ có tham chiếu, bạn sẽ không vô tình lấy cắp nó từ tổ tiên của mình. Bạn sẽ nhận được cùng một số giới thiệu được đính kèm vào phần tử mới của mình.

Một mô hình phổ biến là lập bản đồ qua các con của bạn và thêm một chỗ dựa mới. Đã có nhiều vấn đề được báo cáo về việc cloneWithProps bị mất ref, khiến việc suy luận về mã của bạn trở nên khó khăn hơn. Bây giờ làm theo cùng một mẫu với cloneElement sẽ hoạt động như mong đợi. Ví dụ:

var newChildren = React.Children.map(this.props.children, function(child) {
  return React.cloneElement(child, { foo: true })
});

Lưu ý: React.cloneElement (child, {ref: 'newRef'}) KHÔNG ghi đè ref nên vẫn không thể có hai cha mẹ có ref cho cùng một đứa trẻ, trừ khi bạn sử dụng callback-refs.

Đây là một tính năng quan trọng để có được trong React 0.13 vì các đạo cụ hiện là bất biến. Đường dẫn nâng cấp thường là sao chép phần tử, nhưng làm như vậy bạn có thể mất ref. Do đó, chúng tôi cần một đường dẫn nâng cấp đẹp hơn ở đây. Khi chúng tôi nâng cấp các trang web cuộc gọi tại Facebook, chúng tôi nhận ra rằng chúng tôi cần phương pháp này. Chúng tôi nhận được phản hồi tương tự từ cộng đồng. Do đó, chúng tôi quyết định thực hiện một RC khác trước khi phát hành cuối cùng để đảm bảo rằng chúng tôi có được điều này.

Cuối cùng, chúng tôi dự định sẽ không dùng React.addons.cloneWithProps nữa. Chúng tôi vẫn chưa làm điều đó, nhưng đây là cơ hội tốt để bắt đầu suy nghĩ về cách sử dụng của riêng bạn và cân nhắc sử dụng React.cloneElement thay thế. Chúng tôi chắc chắn sẽ gửi một bản phát hành có thông báo ngừng sử dụng trước khi chúng tôi thực sự xóa bản phát hành đó nên không cần thực hiện hành động ngay lập tức.

thêm ở đây ...

22
Nick Ovchinnikov 2019-02-06 02:13.

Cách tốt nhất cho phép bạn thực hiện chuyển thuộc tính childrengiống như một mẫu hàm https://medium.com/merrickchristensen/ Chức năng-as- child-components-5f3920a9ace9

Đoạn mã: https://stackblitz.com/edit/react-fcmubc

Thí dụ:

const Parent = ({ children }) => {
    const somePropsHere = {
      style: {
        color: "red"
      }
      // any other props here...
    }
    return children(somePropsHere)
}

const ChildComponent = props => <h1 {...props}>Hello world!</h1>

const App = () => {
  return (
    <Parent>
      {props => (
        <ChildComponent {...props}>
          Bla-bla-bla
        </ChildComponent>
      )}
    </Parent>
  )
}

7
poynting 2017-10-17 04:07.

Không câu trả lời nào giải quyết vấn đề có con KHÔNG phải là thành phần React, chẳng hạn như chuỗi văn bản. Một cách giải quyết có thể là như sau:

// Render method of Parent component
render(){
    let props = {
        setAlert : () => {alert("It works")}
    };
    let childrenWithProps = React.Children.map( this.props.children, function(child) {
        if (React.isValidElement(child)){
            return React.cloneElement(child, props);
        }
          return child;
      });
    return <div>{childrenWithProps}</div>

}
6
olenak 2015-12-30 10:05.

Tôi cần thiết để sửa chữa câu trả lời được chấp nhận ở trên để làm cho nó hoạt sử dụng thay vì này con trỏ. Điều này trong phạm vi của hàm bản đồ không có hàm doSomething được định nghĩa.

var Parent = React.createClass({
doSomething: function() {
    console.log('doSomething!');
},

render: function() {
    var that = this;
    var childrenWithProps = React.Children.map(this.props.children, function(child) {
        return React.cloneElement(child, { doSomething: that.doSomething });
    });

    return <div>{childrenWithProps}</div>
}})

Cập nhật: bản sửa lỗi này dành cho ECMAScript 5, trong ES6 không cần var that = this

6
and_rest 2016-11-24 23:24.

Cách sạch hơn khi xem xét một hoặc nhiều trẻ em

<div>
   { React.Children.map(this.props.children, child => React.cloneElement(child, {...this.props}))}
</div>
5
Nesha Zoric 2018-03-02 05:12.

Nếu bạn có nhiều con bạn muốn chuyển đạo cụ cho, bạn có thể thực hiện theo cách này, sử dụng React.Children.map:

render() {
    let updatedChildren = React.Children.map(this.props.children,
        (child) => {
            return React.cloneElement(child, { newProp: newProp });
        });

    return (
        <div>
            { updatedChildren }
        </div>
    );
}

Nếu thành phần của bạn chỉ có một con, thì không cần ánh xạ, bạn có thể cloneElement ngay lập tức:

render() {
    return (
        <div>
            {
                React.cloneElement(this.props.children, {
                    newProp: newProp
                })
            }
        </div>
    );
}
5
yeasayer 2016-11-03 01:59.

Bạn không cần nữa {this.props.children}. Bây giờ bạn có thể quấn thành phần con bạn sử dụng rendertrong Routevà thông qua đạo cụ của bạn như bình thường:

<BrowserRouter>
  <div>
    <ul>
      <li><Link to="/">Home</Link></li>
      <li><Link to="/posts">Posts</Link></li>
      <li><Link to="/about">About</Link></li>
    </ul>

    <hr/>

    <Route path="/" exact component={Home} />
    <Route path="/posts" render={() => (
      <Posts
        value1={1}
        value2={2}
        data={this.state.data}
      />
    )} />
    <Route path="/about" component={About} />
  </div>
</BrowserRouter>
4
Maksim Kostromin 2016-11-04 16:33.

Parent.jsx:

import React from 'react';

const doSomething = value => {};

const Parent = props => (
  <div>
    {
      !props || !props.children 
        ? <div>Loading... (required at least one child)</div>
        : !props.children.length 
            ? <props.children.type {...props.children.props} doSomething={doSomething} {...props}>{props.children}</props.children.type>
            : props.children.map((child, key) => 
              React.cloneElement(child, {...props, key, doSomething}))
    }
  </div>
);

Child.jsx:

import React from 'react';

/* but better import doSomething right here,
   or use some flux store (for example redux library) */
export default ({ doSomething, value }) => (
  <div onClick={() => doSomething(value)}/>
);

và main.jsx:

import React from 'react';
import { render } from 'react-dom';
import Parent from './Parent';
import Child from './Child';

render(
  <Parent>
    <Child/>
    <Child value='1'/>
    <Child value='2'/>
  </Parent>,
  document.getElementById('...')
);

xem ví dụ tại đây: https://plnkr.co/edit/jJHQECrKRrtKlKYRpIWl?p=preview

4
Alexandr Cherednichenko 2018-02-11 11:19.

Có lẽ bạn cũng có thể thấy tính năng này hữu ích, mặc dù nhiều người đã coi đây là một tính năng chống lại mô hình, nó vẫn có thể được sử dụng nếu bạn biết mình đang làm gì và thiết kế tốt giải pháp của mình.

Chức năng như các thành phần con

3
Shubham Khatri 2018-01-11 19:57.

Theo tài liệu của cloneElement()

React.cloneElement(
  element,
  [props],
  [...children]
)

Sao chép và trả về một phần tử React mới bằng cách sử dụng phần tử làm điểm bắt đầu. Phần tử kết quả sẽ có các đạo cụ của phần tử ban đầu với các đạo cụ mới được hợp nhất một cách nông cạn. Những đứa trẻ mới sẽ thay thế những đứa trẻ hiện có. key và ref từ phần tử gốc sẽ được giữ nguyên.

React.cloneElement() gần như tương đương với:

<element.type {...element.props} {...props}>{children}</element.type>

Tuy nhiên, nó cũng bảo tồn các ref. Điều này có nghĩa là nếu bạn có được một đứa trẻ có tham chiếu, bạn sẽ không vô tình lấy cắp nó từ tổ tiên của mình. Bạn sẽ nhận được cùng một số giới thiệu được đính kèm vào phần tử mới của mình.

Vì vậy, cloneElement là thứ bạn sẽ sử dụng để cung cấp các đạo cụ tùy chỉnh cho trẻ em. Tuy nhiên, có thể có nhiều con trong thành phần và bạn sẽ cần lặp lại nó. Những câu trả lời khác gợi ý cho bạn là để lập bản đồ trên chúng bằng cách sử dụng React.Children.map. Tuy nhiên, React.Children.mapkhông giống như React.cloneElementthay đổi các khóa của Phần tử thêm vào và thêm .$vào như tiền tố. Kiểm tra câu hỏi này để biết thêm chi tiết: React.cloneElement bên trong React.Children.map đang khiến các khóa phần tử thay đổi

Nếu bạn muốn tránh nó, thay vào đó bạn nên chuyển sang forEachhàm như

render() {
    const newElements = [];
    React.Children.forEach(this.props.children, 
              child => newElements.push(
                 React.cloneElement(
                   child, 
                   {...this.props, ...customProps}
                )
              )
    )
    return (
        <div>{newElements}</div>
    )

}
3
ZEE 2019-04-20 04:59.

Tôi nghĩ kết xuất hỗ trợ là cách thích hợp để xử lý tình huống này

Bạn cho phép Parent cung cấp các đạo cụ cần thiết được sử dụng trong thành phần con, bằng cách cấu trúc lại mã Parent để trông giống như sau:

const Parent = ({children}) => {
  const doSomething(value) => {}

  return children({ doSomething })
}

Sau đó, trong Thành phần con, bạn có thể truy cập vào chức năng do cha mẹ cung cấp theo cách này:

class Child extends React {

  onClick() => { this.props.doSomething }

  render() { 
    return (<div onClick={this.onClick}></div>);
  }

}

Bây giờ cấu trúc fianl sẽ trông như thế này:

<Parent>
  {(doSomething) =>
   (<Fragment>
     <Child value="1" doSomething={doSomething}>
     <Child value="2" doSomething={doSomething}>
    <Fragment />
   )}
</Parent>
3
Ben Carp 2019-06-24 03:44.

Phương pháp 1 - nhân bản trẻ em

const Parent = (props) => {
   const attributeToAddOrReplace= "Some Value"
   const childrenWithAdjustedProps = React.Children.map(props.children, child =>
      React.cloneElement(child, { attributeToAddOrReplace})
   );

   return <div>{childrenWithAdjustedProps }</div>
}

Phương pháp 2 - sử dụng ngữ cảnh có thể kết hợp

Ngữ cảnh cho phép bạn chuyển một chỗ dựa cho một thành phần con sâu mà không cần chuyển nó một cách rõ ràng làm chỗ dựa qua các thành phần ở giữa.

Bối cảnh đi kèm với những hạn chế:

  1. Dữ liệu không lưu chuyển theo cách thông thường - thông qua đạo cụ.
  2. Sử dụng ngữ cảnh tạo ra một hợp đồng giữa người tiêu dùng và nhà cung cấp. Có thể khó hiểu và tái tạo các yêu cầu cần thiết để sử dụng lại một thành phần.

Sử dụng ngữ cảnh có thể kết hợp

export const Context = createContext<any>(null);

export const ComposableContext = ({ children, ...otherProps }:{children:ReactNode, [x:string]:any}) => {
    const context = useContext(Context)
    return(
      <Context.Provider {...context} value={{...context, ...otherProps}}>{children}</Context.Provider>
    );
}

function App() {
  return (
      <Provider1>
            <Provider2> 
                <Displayer />
            </Provider2>
      </Provider1>
  );
}

const Provider1 =({children}:{children:ReactNode}) => (
    <ComposableContext greeting="Hello">{children}</ComposableContext>
)

const Provider2 =({children}:{children:ReactNode}) => (
    <ComposableContext name="world">{children}</ComposableContext>
)

const Displayer = () => {
  const context = useContext(Context);
  return <div>{context.greeting}, {context.name}</div>;
};

2
sidonaldson 2017-02-03 01:18.

Ngoài câu trả lời @and_rest, đây là cách tôi sao chép những đứa trẻ và thêm một lớp.

<div className="parent">
    {React.Children.map(this.props.children, child => React.cloneElement(child, {className:'child'}))}
</div>
2
amaster 2020-04-25 07:17.

Khi sử dụng các thành phần chức năng, bạn sẽ thường gặp TypeError: Cannot add property myNewProp, object is not extensiblelỗi khi cố gắng thiết lập các thuộc tính mới props.children. Có một công việc xung quanh vấn đề này bằng cách nhân bản các đạo cụ và sau đó nhân bản chính đứa trẻ với các đạo cụ mới.

const MyParentComponent = (props) => {
  return (
    <div className='whatever'>
      {props.children.map((child) => {
        const newProps = { ...child.props }
        // set new props here on newProps
        newProps.myNewProp = 'something'
        const preparedChild = { ...child, props: newProps }
        return preparedChild
      })}
    </div>
  )
}
1
nitte93user3232918 2016-07-06 20:31.

Cách trơn tru nhất để làm điều này:

    {React.cloneElement(this.props.children, this.props)}
1
user10884362 2019-01-09 03:01.

Đối với bất kỳ ai có một phần tử con duy nhất, điều này nên làm điều đó.

{React.isValidElement(this.props.children)
                  ? React.cloneElement(this.props.children, {
                      ...prop_you_want_to_pass
                    })
                  : null}
1
DonKoko 2020-08-27 05:14.

Lấy cảm hứng từ tất cả các câu trả lời ở trên và đây là những gì tôi đã làm. Tôi đang chuyển một số đạo cụ như một số dữ liệu và một số thành phần.

import React from "react";

const Parent = ({ children }) => {
  const { setCheckoutData } = actions.shop;
  const { Input, FieldError } = libraries.theme.components.forms;

  const onSubmit = (data) => {
    setCheckoutData(data);
  };

  const childrenWithProps = React.Children.map(
    children,
    (child) =>
      React.cloneElement(child, {
        Input: Input,
        FieldError: FieldError,
        onSubmit: onSubmit,
      })
  );

  return <>{childrenWithProps}</>;
};

0
amit_183 2015-09-03 23:02.

Đây có phải là những gì bạn yêu cầu?

var Parent = React.createClass({
  doSomething: function(value) {
  }
  render: function() {
    return  <div>
              <Child doSome={this.doSomething} />
            </div>
  }
})

var Child = React.createClass({
  onClick:function() {
    this.props.doSome(value); // doSomething is undefined
  },  
  render: function() {
    return  <div onClick={this.onClick}></div>
  }
})
0
aWebDeveloper 2017-12-27 22:54.

Một số lý do React.children không hoạt động với tôi. Đây là những gì làm việc cho tôi.

Tôi chỉ muốn thêm một lớp học cho đứa trẻ. tương tự như thay đổi một chỗ dựa

 var newChildren = this.props.children.map((child) => {
 const className = "MenuTooltip-item " + child.props.className;
    return React.cloneElement(child, { className });
 });

 return <div>{newChildren}</div>;

Thủ thuật ở đây là React.cloneElement . Bạn có thể vượt qua bất kỳ chỗ dựa nào theo cách tương tự

0
omeralper 2019-02-20 14:47.

Render đạo cụ là cách tiếp cận chính xác nhất cho vấn đề này. Thay vì chuyển thành phần con cho thành phần cha làm đạo cụ con, hãy để cha mẹ hiển thị thành phần con theo cách thủ công. Render là đạo cụ tích hợp sẵn trong react, lấy tham số hàm. Trong hàm này, bạn có thể cho phép thành phần mẹ hiển thị bất kỳ thứ gì bạn muốn với các tham số tùy chỉnh. Về cơ bản, nó hoạt động tương tự như đạo cụ trẻ em nhưng nó có thể tùy chỉnh nhiều hơn.

class Child extends React.Component {
  render() {
    return <div className="Child">
      Child
      <p onClick={this.props.doSomething}>Click me</p>
           {this.props.a}
    </div>;
  }
}

class Parent extends React.Component {
  doSomething(){
   alert("Parent talks"); 
  }

  render() {
    return <div className="Parent">
      Parent
      {this.props.render({
        anythingToPassChildren:1, 
        doSomething: this.doSomething})}
    </div>;
  }
}

class Application extends React.Component {
  render() {
    return <div>
      <Parent render={
          props => <Child {...props} />
        }/>
    </div>;
  }
}

Ví dụ tại codepen

0
Kalpesh Popat 2020-08-13 21:44.

Tôi đến với bài đăng này khi đang nghiên cứu cho một nhu cầu tương tự, nhưng tôi cảm thấy giải pháp nhân bản quá phổ biến, quá thô và khiến tôi mất tập trung vào chức năng.

Tôi đã tìm thấy một bài báo trong tài liệu phản ứng Các thành phần thứ tự cao hơn

Đây là mẫu của tôi:

import React from 'react';

const withForm = (ViewComponent) => {
    return (props) => {

        const myParam = "Custom param";

        return (
            <>
                <div style={{border:"2px solid black", margin:"10px"}}>
                    <div>this is poc form</div>
                    <div>
                        <ViewComponent myParam={myParam} {...props}></ViewComponent>
                    </div>
                </div>
            </>
        )
    }
}

export default withForm;


const pocQuickView = (props) => {
    return (
        <div style={{border:"1px solid grey"}}>
            <div>this is poc quick view and it is meant to show when mouse hovers over a link</div>
        </div>
    )
}

export default withForm(pocQuickView);

Đối với tôi, tôi đã tìm thấy một giải pháp linh hoạt trong việc triển khai mô hình Thành phần thứ tự cao hơn.

Tất nhiên nó phụ thuộc vào chức năng, nhưng sẽ tốt nếu ai đó đang tìm kiếm một yêu cầu tương tự, nó sẽ tốt hơn nhiều so với việc phụ thuộc vào mã phản ứng mức thô như sao chép.

Mẫu khác mà tôi tích cực sử dụng là mẫu vùng chứa. đọc về nó, có rất nhiều bài báo ra khỏi đó.

Related questions

MORE COOL STUFF

Cate Blanchett chia tay chồng sau 3 ngày bên nhau và vẫn kết hôn với anh ấy 25 năm sau

Cate Blanchett chia tay chồng sau 3 ngày bên nhau và vẫn kết hôn với anh ấy 25 năm sau

Cate Blanchett đã bất chấp những lời khuyên hẹn hò điển hình khi cô gặp chồng mình.

Tại sao Michael Sheen là một diễn viên phi lợi nhuận

Tại sao Michael Sheen là một diễn viên phi lợi nhuận

Michael Sheen là một diễn viên phi lợi nhuận nhưng chính xác thì điều đó có nghĩa là gì?

Hallmark Star Colin Egglesfield Các món ăn gây xúc động mạnh đối với người hâm mộ tại RomaDrama Live! [Loại trừ]

Hallmark Star Colin Egglesfield Các món ăn gây xúc động mạnh đối với người hâm mộ tại RomaDrama Live! [Loại trừ]

Ngôi sao của Hallmark Colin Egglesfield chia sẻ về những cuộc gặp gỡ với người hâm mộ ly kỳ tại RomaDrama Live! cộng với chương trình INSPIRE của anh ấy tại đại hội.

Tại sao bạn không thể phát trực tuyến 'chương trình truyền hình phía Bắc'

Tại sao bạn không thể phát trực tuyến 'chương trình truyền hình phía Bắc'

Bạn sẽ phải phủi sạch đầu đĩa Blu-ray hoặc DVD để xem tại sao Northern Exposure trở thành một trong những chương trình nổi tiếng nhất của thập niên 90.

Where in the World Are You? Take our GeoGuesser Quiz

Where in the World Are You? Take our GeoGuesser Quiz

The world is a huge place, yet some GeoGuessr players know locations in mere seconds. Are you one of GeoGuessr's gifted elite? Take our quiz to find out!

8 công dụng tuyệt vời của Baking Soda và Giấm

8 công dụng tuyệt vời của Baking Soda và Giấm

Bạn biết đấy, hai sản phẩm này là nguồn điện để làm sạch, riêng chúng. Nhưng cùng với nhau, chúng có một loạt công dụng hoàn toàn khác.

Hạn hán, biến đổi khí hậu đe dọa tương lai của thủy điện Hoa Kỳ

Hạn hán, biến đổi khí hậu đe dọa tương lai của thủy điện Hoa Kỳ

Thủy điện rất cần thiết cho lưới điện của Hoa Kỳ, nhưng nó chỉ tạo ra năng lượng khi có nước di chuyển. Bao nhiêu nhà máy thủy điện có thể gặp nguy hiểm khi các hồ và sông cạn kiệt?

Quyên góp tóc của bạn để giúp giữ nước sạch của chúng tôi

Quyên góp tóc của bạn để giúp giữ nước sạch của chúng tôi

Tóc tỉa từ các tiệm và các khoản quyên góp cá nhân có thể được tái sử dụng như những tấm thảm thấm dầu và giúp bảo vệ môi trường.

Đây là Tổng thống Trump đe dọa 'trợ cấp' xe điện của GM vì đóng cửa nhà máy

Đây là Tổng thống Trump đe dọa 'trợ cấp' xe điện của GM vì đóng cửa nhà máy

Trump và Giám đốc điều hành GM Mary Barra vào năm 2017. Kể từ khi tin tức nổ ra ngày hôm qua rằng General Motors đang cắt giảm việc làm ở Bắc Mỹ để chuẩn bị cho tương lai điện / xe tự hành / khủng khiếp có thể xảy ra của chúng tôi, gần như tất cả mọi người đã tự hỏi: Tổng thống Trump, người đã vận động tranh cử trên một nền tảng sẽ như thế nào của việc mang lại và duy trì việc làm ô tô của Mỹ, phải nói gì về điều này? Bây giờ chúng ta biết.

Bản vá lỗi tiếp theo của Fallout 76 sẽ mang lại một số bản sửa lỗi cần thiết

Bản vá lỗi tiếp theo của Fallout 76 sẽ mang lại một số bản sửa lỗi cần thiết

Bethesda cho biết ngày hôm nay trên Reddit, Fallout 76 sẽ có một bản vá lớn khác vào ngày 4 tháng 12, sẽ bắt đầu cố gắng khắc phục một số vấn đề lớn hơn của trò chơi. Ngoài ra, công ty cho biết họ có kế hoạch giao tiếp nhiều hơn trong tương lai về những gì nhóm Fallout 76 đang làm việc và khi nào các bản cập nhật mới cho trò chơi sẽ ra mắt.

Mạng lưới bệnh viện Công giáo sẽ không cho phép nhân viên phá thai tại phòng khám ngoài giờ làm việc

Mạng lưới bệnh viện Công giáo sẽ không cho phép nhân viên phá thai tại phòng khám ngoài giờ làm việc

Bạn có biết rằng một trong sáu bệnh nhân ở bệnh viện ở Hoa Kỳ được điều trị tại một cơ sở Công giáo? Và bạn có biết rằng quyền sở hữu của Công giáo hạn chế sâu sắc việc thiết lập các thủ tục y tế có thể được thực hiện trong các bệnh viện này, rõ ràng nhất là khi nói đến chăm sóc sức khỏe sinh sản? Bây giờ NPR báo cáo rằng sự gia tăng của các bệnh viện thuộc Công giáo đang gây khó khăn hơn cho các bác sĩ — những người bị cấm bởi các quy định do Hoa Kỳ viết.

Khói từ đám cháy rừng ở California đã đến tận thành phố New York

Khói từ đám cháy rừng ở California đã đến tận thành phố New York

Đường chân trời San Francisco bị che khuất bởi khói và khói mù do cháy rừng phía sau Đảo Alcatraz, Thứ Tư, ngày 14 tháng 11 năm 2018, ở San Francisco.

Nicky Hilton Forced to Borrow Paris' 'I Love Paris' Sweatshirt After 'Airline Loses All [My] Luggage'

Nicky Hilton Forced to Borrow Paris' 'I Love Paris' Sweatshirt After 'Airline Loses All [My] Luggage'

Nicky Hilton Rothschild's luggage got lost, but luckily she has an incredible closet to shop: Sister Paris Hilton's!

Kate Middleton dành một ngày bên bờ nước ở London, cùng với Jennifer Lopez, Julianne Hough và hơn thế nữa

Kate Middleton dành một ngày bên bờ nước ở London, cùng với Jennifer Lopez, Julianne Hough và hơn thế nữa

Kate Middleton dành một ngày bên bờ nước ở London, cùng với Jennifer Lopez, Julianne Hough và hơn thế nữa. Từ Hollywood đến New York và mọi nơi ở giữa, hãy xem các ngôi sao yêu thích của bạn đang làm gì!

17 tuổi bị đâm chết trong khi 4 người khác bị thương trong một cuộc tấn công bằng dao trên sông Wisconsin

17 tuổi bị đâm chết trong khi 4 người khác bị thương trong một cuộc tấn công bằng dao trên sông Wisconsin

Các nhà điều tra đang xem xét liệu nhóm và nghi phạm có biết nhau trước vụ tấn công hay không

Thanh thiếu niên, Gia đình Florida Hội đồng quản trị trường học về Luật 'Không nói đồng tính': 'Buộc chúng tôi tự kiểm duyệt'

Thanh thiếu niên, Gia đình Florida Hội đồng quản trị trường học về Luật 'Không nói đồng tính': 'Buộc chúng tôi tự kiểm duyệt'

Vụ kiện, nêu tên một số học khu, lập luận rằng dự luật "Không nói đồng tính" được ban hành gần đây của Florida "có hiệu quả im lặng và xóa bỏ học sinh và gia đình LGBTQ +"

Đường băng hạ cánh

Đường băng hạ cánh

Cuối hè đầu thu là mùa hoài niệm. Những chiếc đèn đường chiếu ánh sáng của chúng qua những con đường đẫm mưa, và những chiếc lá dưới chân - màu đỏ cam tắt trong bóng chạng vạng - là lời nhắc nhở về những ngày đã qua.

Hãy tưởng tượng tạo ra một chiến lược nội dung thực sự CHUYỂN ĐỔI. Nó có thể.

Hãy tưởng tượng tạo ra một chiến lược nội dung thực sự CHUYỂN ĐỔI. Nó có thể.

Vào năm 2021, tôi khuyến khích bạn suy nghĩ lại mọi thứ bạn biết về khách hàng mà bạn phục vụ và những câu chuyện bạn kể cho họ. Lùi lại.

Sự mất mát của voi ma mút đã mở ra trái tim tôi để yêu

Sự mất mát của voi ma mút đã mở ra trái tim tôi để yêu

Vào ngày sinh nhật thứ 9 của Felix The Cat, tôi nhớ về một trong những mất mát lớn nhất trong cuộc đời trưởng thành của tôi - Sophie của tôi vào năm 2013. Tôi đã viết bài luận này và chia sẻ nó trên nền tảng này một thời gian ngắn vào năm 2013.

Khi bạn không thể trở thành người mà Internet muốn bạn trở thành

Khi bạn không thể trở thành người mà Internet muốn bạn trở thành

Tôi ghét từ "tàu đắm". Mọi người cảm thấy thoải mái trong la bàn đạo đức của riêng mình, và khi làm như vậy, họ thấy mình vượt qua sự phán xét.

Language