【问题标题】:Dynamically generating components in React-Bootstrap在 React-Bootstrap 中动态生成组件
【发布时间】:2014-09-28 07:45:27
【问题描述】:

我试图通过实例化 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 组件似乎无关紧要,但我发现它们是满足反应框架所必需的。实际上,我会将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-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>

【问题讨论】:

    标签: javascript twitter-bootstrap reactjs react-bootstrap


    【解决方案1】:

    我解决了这个问题。解决方案是创建一个表示一组警报的特殊反应组件。显然,只能从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')
    );
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-07-26
      • 2022-10-15
      • 1970-01-01
      • 2019-04-21
      • 2017-11-26
      • 1970-01-01
      • 2021-10-02
      • 1970-01-01
      相关资源
      最近更新 更多