Tự động thêm các thành phần con trong React


86

Mục tiêu của tôi là thêm động các thành phần trên một trang / thành phần chính.

Tôi đã bắt đầu với một số mẫu ví dụ cơ bản như sau:

main.js:

var App = require('./App.js');
var SampleComponent = require('./SampleComponent.js');
ReactDOM.render(<App/>, document.body);
ReactDOM.render(<SampleComponent name="SomeName"/>, document.getElementById('myId'));

App.js:

var App = React.createClass({
    render: function() {
        return (
            <div>
                <h1>App main component! </h1>
                <div id="myId">myId div</div>
            </div>

        );
    }

});

SampleComponent.js:

var SampleComponent = React.createClass({
    render: function() {
        return (
            <div>
                <h1>Sample Component! </h1>
            </div>
        );
    }
});

Ở đây SampleComponentđược gắn kết với <div id="myId"></div>nút, được viết App.jssẵn trong mẫu. Nhưng điều gì sẽ xảy ra nếu tôi cần thêm số lượng thành phần không xác định vào Thành phần ứng dụng? Rõ ràng là tôi không thể có tất cả các div cần thiết ngồi ở đó.

Sau khi đọc một số hướng dẫn, tôi vẫn không hiểu về cách các thành phần được tạo và thêm động vào thành phần mẹ. Một cách để làm điều đó là gì?


2
Có lý do tại sao cả hai thành phần của bạn gắn kết với các phần tử khác nhau? 99% Phản ứng ứng dụng chỉ gọi ReactDOM.rendermột lần và tất cả các thành phần khác là con của các 'root' nút
azium

1
Không, bây giờ tôi hiểu điều này là không đúng :)
Justin Trevein

Câu trả lời:


67

Bạn cần chuyển các thành phần của mình khi còn nhỏ, như sau:

var App = require('./App.js');
var SampleComponent = require('./SampleComponent.js');
ReactDOM.render(
    <App>
        <SampleComponent name="SomeName"/> 
    <App>, 
    document.body
);

Và sau đó nối chúng vào phần thân của thành phần:

var App = React.createClass({
    render: function() {
        return (
            <div>
                <h1>App main component! </h1>
                {
                    this.props.children
                }
            </div>
        );
    }
});

Bạn không cần phải thao tác thủ công với mã HTML, React sẽ làm điều đó cho bạn. Nếu bạn muốn thêm một số thành phần con, bạn chỉ cần thay đổi đạo cụ hoặc trạng thái tùy theo. Ví dụ:

var App = React.createClass({

    getInitialState: function(){
        return [
            {id:1,name:"Some Name"}
        ]
    },

    addChild: function() {
        // State change will cause component re-render
        this.setState(this.state.concat([
            {id:2,name:"Another Name"}
        ]))
    }

    render: function() {
        return (
            <div>
                <h1>App main component! </h1>
                <button onClick={this.addChild}>Add component</button>
                {
                    this.state.map((item) => (
                        <SampleComponent key={item.id} name={item.name}/>
                    ))
                }
            </div>
        );
    }

});

2
Cảm ơn! Tôi đã bỏ lỡ thực tế là các thành phần có thể được xác định trong render () dựa trên trạng thái của chúng. Câu trả lời của bạn ở đây là hoàn thành một phần lớn (đề cập Populating nhà nước với các thành phần) và trả lời câu hỏi chính xác :)
Justin Trevein

Làm thế nào để bạn chuyển đạo cụ cho những đứa trẻ đã được thêm vào?
BrightIntelDusk

Vì vậy, để theo dõi điều này: nếu tôi muốn tạo một ứng dụng trang duy nhất có nhiều tab và cửa sổ bật lên từ các nút, tôi cần tiếp tục và hiển thị các thành phần đó (trống), ẩn chúng (bằng cách nào đó) và sau đó sửa đổi trạng thái để tạo chúng "xuất hiện" vào đúng thời điểm? Nếu bạn đang cố gắng tạo một ứng dụng trang đơn nhiều tab trong React thì đó có phải là cách tốt nhất để nghĩ về nó không? Hay tôi đang thiếu cái gì đó? Cảm ơn bạn!
Elisabeth

1
@Elisabeth Vâng, đúng vậy. Bạn thực sự có hai tùy chọn chính: hoặc luôn hiển thị mọi thứ và chỉ ẩn mọi thứ bằng cách sử dụng CSS, áp dụng các lớp CSS hoặc kiểu nội tuyến có điều kiện; hoặc hiển thị mọi thứ theo điều kiện, trả về phần tử React hoặc null tùy thuộc vào trạng thái ứng dụng của bạn. Hai cách tiếp cận này có ưu và nhược điểm và thường được sử dụng cả trong cùng một ứng dụng cho các thành phần khác nhau tùy thuộc vào nhu cầu của bạn.
Nikolai Mavrenkov 23/03/18

1
Cảm ơn Nikolai! Điều đó thực sự giúp củng cố mọi thứ trong tâm trí tôi về React. Đó là một cách rất khác để thiết kế ứng dụng và suy nghĩ về DOM so với cách tôi sử dụng với JavaScript đơn thuần và jQuery.
Elisabeth

6

Đầu tiên, tôi sẽ không sử dụng document.body . Thay vào đó, hãy thêm một vùng chứa trống:

index.html:

<html>
    <head></head>
    <body>
        <div id="app"></div>
    </body>
</html>

Sau đó chọn chỉ hiển thị <App />phần tử của bạn :

main.js:

var App = require('./App.js');
ReactDOM.render(<App />, document.getElementById('app'));

Bên trong, App.jsbạn có thể nhập các thành phần khác của mình và hoàn toàn bỏ qua mã kết xuất DOM của mình:

App.js:

var SampleComponent = require('./SampleComponent.js');

var App = React.createClass({
    render: function() {
        return (
            <div>
                <h1>App main component!</h1>
                <SampleComponent name="SomeName" />
            </div>
        );
    }
});

SampleComponent.js:

var SampleComponent = React.createClass({
    render: function() {
        return (
            <div>
                <h1>Sample Component!</h1>
            </div>
        );
    }
});

Sau đó, bạn có thể tương tác theo chương trình với bất kỳ số lượng thành phần nào bằng cách nhập chúng vào các tệp thành phần cần thiết bằng cách sử dụng require.


Không vấn đề gì, tôi chỉ có thể nhìn thấy ai đó sao chép dán nó và sau đó chi tiêu giờ vào nó ...
Neil Xoay

6

Chia sẻ giải pháp của tôi ở đây, dựa trên câu trả lời của Chris. Hy vọng nó có thể giúp ích cho những người khác.

Tôi cần nối động các phần tử con vào JSX của mình, nhưng theo cách đơn giản hơn so với kiểm tra có điều kiện trong câu lệnh trả về của tôi. Tôi muốn hiển thị một trình tải trong trường hợp các phần tử con chưa sẵn sàng. Nó đây:

export class Settings extends React.PureComponent {
  render() {
    const loading = (<div>I'm Loading</div>);
    let content = [];
    let pushMessages = null;
    let emailMessages = null;

    if (this.props.pushPreferences) {
       pushMessages = (<div>Push Content Here</div>);
    }
    if (this.props.emailPreferences) {
      emailMessages = (<div>Email Content Here</div>);
    }

    // Push the components in the order I want
    if (emailMessages) content.push(emailMessages);
    if (pushMessages) content.push(pushMessages);

    return (
      <div>
        {content.length ? content : loading}
      </div>
    )
}

Bây giờ, tôi nhận ra rằng tôi cũng có thể chỉ cần đặt {pushMessages}{emailMessages}trực tiếp vào return()bên dưới của tôi , nhưng giả sử tôi có nội dung có điều kiện hơn, thì nội dung của tôi return()sẽ trông lộn xộn.


4

Đầu tiên, một cảnh báo: bạn không bao giờ nên mày mò DOM được quản lý bởi React, mà bạn đang thực hiện bằng cách gọi ReactDOM.render(<SampleComponent ... />);

Với React, bạn nên sử dụng SampleComponent trực tiếp trong Ứng dụng chính.

var App = require('./App.js');
var SampleComponent = require('./SampleComponent.js');
ReactDOM.render(<App/>, document.body);

Nội dung của Thành phần của bạn không liên quan, nhưng nó nên được sử dụng như sau:

var App = React.createClass({
    render: function() {
        return (
            <div>
                <h1>App main component! </h1>
                <SampleComponent name="SomeName"/>
            </div>
        );
    }
});

Sau đó, bạn có thể mở rộng thành phần ứng dụng của mình để sử dụng danh sách.

var App = React.createClass({
    render: function() {
        var componentList = [
            <SampleComponent name="SomeName1"/>,
            <SampleComponent name="SomeName2"/>
        ]; // Change this to get the list from props or state
        return (
            <div>
                <h1>App main component! </h1>
                {componentList}
            </div>
        );
    }
});

Tôi thực sự khuyên bạn nên xem tài liệu React sau đó làm theo hướng dẫn "Bắt đầu". Thời gian bạn dành cho việc đó sẽ được đền đáp sau này.

https://facebook.github.io/react/index.html


Làm thế nào mảng sẽ điền thành phần con mà không cần ánh xạ?
solanki ...

1
@solanki ... Chỉ cần ánh xạ khi danh sách không phải là danh sách các thành phần React. Danh sách ở đây gồm hai SampleComponents, do đó không yêu cầu ánh xạ. Nếu danh sách là một danh sách các tên, thì nó sẽ yêu cầu ánh xạ tới các thành phần React.
Neil Twist

@solanki ... Hãy nhớ rằng đầu ra của các bản đồ chỉ đơn giản là một danh sách
Neil Xoay

1
Chính xác những gì tôi đang tìm kiếm. Trường hợp sử dụng của tôi cần tùy chọn đẩy các thành phần JSX vào một trống <div>được gán cho một biến sau đó được chèn vào JSX như {content}trong câu lệnh trả về của tôi. Sử dụng một mảng trống quá dễ dàng!
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.