1

Javascript クラスからコンポーネントをインスタンス化することにより、実行時に React-Bootstrap でアラート コンポーネントを動的に生成しようとしています。私がこれを行っているのは、表示するアラートがたくさんあり、Javascript クラスの作成がより簡潔であるためです。

これを行う私の試みはうまくいきません。問題が一般的に React に当てはまるのか、それとも単に React-Bootstrap に当てはまるのかはわかりません。ただし、react.js でエラーが発生し、以下がスローされます。

TypeError: undefined is not a function

スローはalert.getComponent()、次の JSX ファイルの呼び出しで発生します。

/** @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インスタンスを反応状態で保存し、それらから反応ノードを生成します。

これについての適切な方法は何ですか?

ここにヒントがあります。次のハードコーディングされたアラートに置き換える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ただし、内部のコードを上記のハードコードされたアラートに単純に置き換えると、TypeError以前と同じメッセージが表示されます。

完全を期すために、ここに私の HTML ソースを示します。これは、react および react-boostv0.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>
4

1 に答える 1

2

問題を解決しました。解決策は、一連のアラートを表す特別な反応コンポーネントを作成することでした。React.createClass()どうやら、定義内からコンポーネント パラメータの自動変数またはオブジェクト変数を参照することしかできないようです。おそらくこれは、react の論理的な制約ではなく、JSX の構文上の制約です。

このソリューションが機能する理由がわかりません。今後同様のトラブルに巻き込まれないよう、何卒ご理解を賜りますようお願い申し上げます。私が違反している一般原則と、代わりに従うべき一般原則 (ここで述べたことよりも洞察力のあるもの) を説明できる場合は、あなたの回答をこの質問に対する「回答」としてマークします。自分の柔軟性がどの程度なのか知りたいです。

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')
);
于 2014-08-05T22:08:03.350 に答える