动态渲染 React 组件

Posted

技术标签:

【中文标题】动态渲染 React 组件【英文标题】:Dynamically Rendering a React component 【发布时间】:2014-12-18 13:30:16 【问题描述】:

在 React JSX 中似乎不可能做这样的事情:

render: function() 
  return (
    <this.props.component.slug className='text'>
      this.props.component.value
    </this.props.component.slug>
  );

我得到一个解析错误:Unexpected token .这不是反应吗 可以处理吗?

我正在设计这个组件,以便在后台,this.props.component.slug 中存储的值将包含有效的 html 元素(h1、p 等)。有什么办法可以做到吗?

【问题讨论】:

【参考方案1】:

您不应该将组件 slug 放在花括号中:

var Hello = React.createClass(
    render: function() 
        return <this.props.component.slug className='text'>
            this.props.component.value
        </this.props.component.slug>;
    
);

React.renderComponent(<Hello component=slug:React.DOM.div, value:'This is my header' />, document.body);

这是一个有效的小提琴:http://jsfiddle.net/kb3gN/6668/

此外,您会发现 JSX 编译器有助于调试这些类型的错误: http://facebook.github.io/react/jsx-compiler.html

【讨论】:

我刚刚解决的一个问题是,您必须提供一个点才能识别任何其他变量,即 var page; &lt;page&gt;&lt;/page&gt; 不起作用而 var page = component: component ; &lt;page.component&gt;&lt;/page.component&gt; 起作用 React 将变量视为自定义元素,如果它们是大写的或有点符号的,否则是 HTML 元素。 IE。 也可以使用 必须将 React.DOM.div 替换为 'div' 才能正常工作 请记住,您的变量应该包含组件本身,而而不是只是组件的名称作为字符串.【参考方案2】:

正如 nilgun 之前指出的,组件 slug 不应该用花括号包裹。

如果您决定将其存储在变量中,请确保它以大写字母开头。

这是一个例子:

var Home = React.createClass(
  render: function() 
    return (
      <div>
        <h3>This is an input</h3>
        <CustomComponent inputType="input" />
        <h3>This is a text area</h3>
        <CustomComponent inputType="textarea" />
      </div>
    );
  
);

var CustomComponent = React.createClass(
  render: function() 
    // make sure this var starts with a capital letter
    var InputType = this.props.inputType;
    return <InputType />;
  
);

React.render(<Home />, document.getElementById('container'));

这是一个有效的小提琴:https://jsfiddle.net/janklimo/yc3qcd0u/

【讨论】:

你摇滚!!变量名应以大写字母开头。这很奇怪,但就是这样。【参考方案3】:

如果您的意图是注入实际渲染的组件,您可以这样做,这对于测试非常方便,或者您希望动态注入组件进行渲染的任何原因。

var MyComponentF=function(ChildComponent)
    var MyComponent = React.createClass(
        getInitialState: function () 
            return 
            ;
        ,
        componentDidMount: function () 
        ,
        render: function () 
            return (
                <div className="MyComponent">
                    <ChildComponent></ChildComponent>
                </div>
            );
        
    );
    return MyComponent;
;

var OtherComponentF=function()
    var OtherComponent = React.createClass(
        getInitialState: function () 
            return 
            ;
        ,
        componentDidMount: function () 
        ,
        render: function () 
            return (
                <div className="OtherComponent">
                    OtherComponent
                </div>
            );
        
    );
    return OtherComponent;
;

var AnotherComponentF=function()
    var AnotherComponent = React.createClass(
        getInitialState: function () 
            return 
            ;
        ,
        componentDidMount: function () 
        ,
        render: function () 
            return (
                <div className="AnotherComponent">
                    AnotherComponent
                </div>
            );
        
    );
    return AnotherComponent;
;

$(document).ready(function () 
    var appComponent = MyComponentF(OtherComponentF());

    // OR
    var appComponent = MyComponentF(AnotherComponentF());

    // Results will differ depending on injected component.

    ReactDOM.render(React.createElement(appComponent), document.getElementById("app-container"));
);

【讨论】:

【参考方案4】:

编辑:可能你忘了在js开头加/** @jsx React.DOM */

您可以使用React.DOM

render: function() 
  return React.DOM[this.props.component.slug](null, this.props.component.value);

http://jsbin.com/rerehutena/2/edit?html,js,output

我不是 React 专家,但我认为每个组件都应该在开始时使用特定的标签来构造。所以它本身可以提出一个明确的目的。

【讨论】:

【参考方案5】:

我的解决方案是将导入的组件分配给一个变量(使用 CapitalCase),然后渲染该变量。

例子:

import React,  Component  from 'react';
import FooComponent from './foo-component';
import BarComponent from './bar-component';

class MyComponent extends Component 
    components = 
        foo: FooComponent,
        bar: BarComponent
    ;

        //this is the most important step
       const TagName = this.components.foo;

    render() 
       return <TagName />
    

export default MyComponent;

【讨论】:

以上是关于动态渲染 React 组件的主要内容,如果未能解决你的问题,请参考以下文章

React 是不是允许动态渲染组件

react-router-dom 开关在动态路径后不渲染组件

React性能优化之减少组件渲染次数

React组件渲染

Vue之重新渲染组件的正确方式

Next.js:如何将仅外部客户端的 React 组件动态导入到开发的服务器端渲染应用程序中?