簡體   English   中英

在React-Bootstrap中動態生成組件

[英]Dynamically generating components in React-Bootstrap

我試圖通過實例化Javascript類中的組件在運行時在React-Bootstrap中動態生成警報組件。 我這樣做是因為有很多警報要顯示,並且因為Javascript類的創建更加簡潔。

我嘗試執行此操作無效。 我不確定這個問題是普遍適用於React還是僅適用於React-Bootstrap。 但是,該錯誤發生在react.js中,並引發以下錯誤:

TypeError: undefined is not a function

引發發生在以下JSX文件中的alert.getComponent()調用中:

/** @jsx React.DOM */

var Alert = ReactBootstrap.Alert;

var AlertDismissible = React.createClass({
    getInitialState: function() {
        return {
            isVisible: true
        };
    },

    render: function() {
        if(!this.state.isVisible)
            return null;

        var message = this.props.message;
        if(this.props.code !== null)
            message = message +'(Code '+ this.props.code +')';
        return (
            <Alert bsStyle={this.props.level} onDismiss={this.dismissAlert}>
                <p>{message}</p>
            </Alert>
        );
    },

    dismissAlert: function() {
        this.setState({isVisible: false});
    }
});

function AlertNotice(level, message, code) {
    this.level = level;
    this.message = message;
    this.code = code || null;
}

AlertNotice.prototype.getComponent = function() {
    // What should go here? Using React.createClass() doesn't help
    return (
        <AlertDismissible level={this.level} message={this.message}
                code={this.code} />
    );
};

function SuccessAlert(message) {
    AlertNotice.call(this, 'success', message);
}
SuccessAlert.prototype = Object.create(AlertNotice);
SuccessAlert.prototype.constructor = SuccessAlert;

/* ...more kinds of alerts... */

function ErrorAlert(message, code) {
    AlertNotice.call(this, 'danger', message, code);
}
ErrorAlert.prototype = Object.create(AlertNotice);
ErrorAlert.prototype.constructor = ErrorAlert;

var SomethingWithAlerts = React.createClass({
    render: function() {
        var alerts = [
            new ErrorAlert("Goof #1", 123),
            new ErrorAlert("Goof #2", 321)
        ].map(function(alert) {
            // react.js throws "TypeError: undefined is not a function"
            return alert.getComponent();
        });
        return (
            <div>{alerts}</div>
        );
    }
});

var TestComponent = (
    <div>
        <SomethingWithAlerts />
    </div>
);

React.renderComponent(
  TestComponent,
  document.getElementById('content')
);

Alert組件來自React-Bootstrap庫。 div組件似乎是多余的,但我發現它們對於滿足react框架是必需的。 實際上,我將以AlertNotice狀態存儲AlertNotice實例,然后根據它們生成AlertNotice節點。

解決此問題的正確方法是什么?

這是一個提示。 如果我替換return alert.getComponent(); 使用以下硬編碼警報,AlertDismissible組件呈現無錯誤(重復),但出現警告:

return (
    <AlertDismissible level="danger" message="Goof" code="777" />
);

以下是通過上述替換得到的警告消息,包括一個鏈接,該鏈接解釋了我應該為每個警報將key=設置為唯一:

Each child in an array should have a unique "key" prop. Check the render method
of SpecimenSetManager. See http://fb.me/react-warning-keys for more information.

但是,如果AlertNotice.prototype.getComponent上述經過硬編碼的警報替換AlertNotice.prototype.getComponent內部的代碼, AlertNotice.prototype.getComponent與以前相同的TypeError消息。

為了完整起見,這是我的HTML來源。 這是react和react-boostrap v0.11.1

<html>
  <head>
    <script src="lib/react.js"></script>
    <script src="lib/react-bootstrap.js"></script>
    <script src="lib/JSXTransformer.js"></script>
    <link rel="stylesheet" href="css/bootstrap-theme.min.css">
    <link rel="stylesheet" href="css/bootstrap.min.css">
  </head>
  <body>
    <div id="content"></div>
    <script src="components.js" type="text/jsx"></script>
  </body>
</html>

我解決了問題。 解決方案是創建一個代表一組警報的特殊反應組件。 顯然,只能從React.createClass()定義中的組件參數中引用自動變量或對象變量。 也許這是JSX的語法約束,而不是react的邏輯約束。

我不明白為什么這種解決方案有效。 我想了解一下,這樣以后就不必再處理類似的問題了。 如果您可以解釋我所違反的一般原則以及應該遵循的一般原則(比我在這里所說的要深刻的話),那么我會將您的回答標記為對這個問題的“答案”。 我想知道我實際上有多少靈活性。

這是起作用的代碼,包括一個新的AlertSet組件:

/** @jsx React.DOM */

function AlertNotice(level, message, code) {
    this.level = level;
    this.message = message;
    this.code = code || null;
}

function SuccessAlert(message) {
    AlertNotice.call(this, 'success', message);
}
SuccessAlert.prototype = Object.create(AlertNotice);
SuccessAlert.prototype.constructor = SuccessAlert;

/* ...more kinds of alerts... */

function ErrorAlert(message, code) {
    AlertNotice.call(this, 'danger', message, code);
}
ErrorAlert.prototype = Object.create(AlertNotice);
ErrorAlert.prototype.constructor = ErrorAlert;

var Alert = ReactBootstrap.Alert;

var AlertDismissible = React.createClass({
    getInitialState: function() {
        return {
            isVisible: true
        };
    },

    render: function() {
        if(!this.state.isVisible)
            return null;

        var message = this.props.message;
        if(this.props.code !== null)
            message = message +'(Code '+ this.props.code +')';
        return (
            <Alert bsStyle={this.props.level} onDismiss={this.dismissAlert}>
                <p>{message}</p>
            </Alert>
        );
    },

    dismissAlert: function() {
        this.setState({isVisible: false});
    }
});

var AlertSet = React.createClass({
    render: function() {
        var alerts = this.props.alerts.map(function(alert, i) {
            return (
                <AlertDismissible key={"alert-"+i} level={alert.level}
                        message={alert.message} code={alert.code} />
            );
        });
        // component must be a single node, so wrap in a div
        return (
            <div>{alerts}</div>
        );
    }
});

var SomethingWithAlerts = React.createClass({
    render: function() {
        var alerts = [
            new ErrorAlert("Goof #1", 123),
            new ErrorAlert("Goof #2", 321)
        ];
        return (
            <AlertSet alerts={alerts} />
        );
    }
});

// TestComponent returns a single node, so doesn't need a div
var TestComponent = (
    <SomethingWithAlerts />
);

React.renderComponent(
  TestComponent,
  document.getElementById('content')
);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM