【问题标题】:React render array of componentsReact 渲染组件数组
【发布时间】:2018-06-16 07:10:18
【问题描述】:

快速提问。有人知道如何渲染一组组件吗?试图让开发人员更容易更改特定组件。 (它就像一个仪表板)。

组件列表文件

import React from 'react';
export default [
    <ComponentOne/>
    <ComponentTwo/>
];

仪表板组件

import React from 'react';

import components from './../../components';

export default class Dashboard extends React.Component 
{
    render = () => {
        //Want to render the array of components here.
        return (
            <div className="tile is-parent">
                {components}
            </div>
        );
    };
}

问题是我有一个组件数组,我需要添加一个键。然而!我似乎也无法为组件添加密钥,不知道如何真正解释它,所以这是我尝试过的代码:

{components.map((component, key) => (
    <component key={key}/>
}

如果我执行上述操作,我不会收到“您必须应用密钥”错误,但是没有任何渲染?而且我猜这是因为“组件”不存在或者沿着这些线有些奇怪。

我也尝试过component.key = key;,但它显然不允许我在这种类型的对象上这样做?

我想我的后备是返回一个速记函数而不是一个数组,但出于某种原因我喜欢这个数组?对小学生来说似乎更简单。

【问题讨论】:

  • 您不能将密钥应用到component,因为它将作为组件的属性。

标签: arrays reactjs


【解决方案1】:

您是否考虑使用新的React Fragments? (在 v16 中)

这将是最简单的解决方案,因为它会绕过整个数组/键问题。

如果您需要传递密钥,那么我建议您只要求组件具有密钥。这就是 React 的工作原理,因此我不建议您将此行为隐藏在可能无法预测的界面后面。

如果你真的需要这样做,那么你可以使用React.cloneElement来克隆元素并注入新的属性:

React.cloneElement(element, { key: 'foo' });

【讨论】:

    【解决方案2】:

    如果你总是想要渲染组件文件中的所有组件,那么最好将它们包装在 React.Fragments 标签中。

    最佳做法是将其导出为一个返回组件的简单函数,而不是一个常量。

    所以...

    const Components = props => {
      return (
        <React.Fragment>
    
          <ComponentOne/>
          <ComponentTwo/>
    
        </React.Fragment>
      )
    }
    
    export default Components
    

    这允许您将多个组件彼此相邻放置,而无需包含它们的 DOM 元素。

    然后你应该能够通过将它用作普通组件来渲染它,它会渲染所有它们,所以只需导入它......

    <Components />
    

    否则,如果您想将它们视为数组,则可以在您导入的 React 对象上免费提供一个函数...

    React.Children.toArray(arrayOfComponents)
    

    您将一个组件数组传递给它(就像在您的原始问题中一样),它允许您在需要时对其进行排序和切片,然后您应该能够将它放在您的渲染函数的返回中

    【讨论】:

      【解决方案3】:

      跟进我的评论,你应该这样做:

      {components.map((component, index) => (
          <span key={index}>
              { component }
          </span>
      }
      

      使用 React 16,您可以使用 React.Fragment:

      {components.map((component, index) => (
          <React.Fragment key={index}>
              { component }
          </React.Fragment>
      }
      

      【讨论】:

      • 除了使用跨度之外,您还可以使用React.Fragment 来避免添加父容器:{component}
      【解决方案4】:

      所有这些答案几乎都是正确的。只需从导出中删除 &lt;../&gt;

      export default [
          ComponentOne,
          ComponentTwo,
      ]
      

      在另一个文件中使用.map():

      export default class Dashboard extends React.Component {
          render = () => (
              <div className="tile is-parent">
                  {components.map((Component, key) => (<Component key={key} />))}
              </div>
          )
      }
      

      另请注意,如果您想像其他人建议的那样使用Fragment,则可以改为使用&lt;&gt;...&lt;/&gt;

      【讨论】:

        【解决方案5】:

        这很简单,只需将您的组件包装到 div 并在那里传递 key,如下所示:

        const Example = ({components}) => (
          <div>
            {components.map((component, i) => <div key={i}>{component}</div>)}    
          </div>
        )
        

        Worked example

        【讨论】:

        • 查看您的工作示例。如果我的渲染部分看起来像这样,我怎么能做到这一点。其中var items = [Foo, Baz]; let items: any[] = items.map(item =&gt; { //alert(tab); return ({item}); });ReactDOM.render( &lt;Example components={items}/&gt;, document.getElementById('container') );
        • 抱歉语法混乱,我做了一个不起作用的小提琴。 jsfiddle.net/208y7mwg
        【解决方案6】:

        你也可以这样做:

        {components.map(component => component)}
        

        它映射您的组件以一一显示它们。

        【讨论】:

          【解决方案7】:

          实际上,您正在从文件中导出 elements 数组。一种方法是导出组件数组并渲染它们

          import React from 'react';
          export default [
              ComponentOne
              ComponentTwo
          ];
          // Then following will work
          {components.map((Component, key) => (
              // Remember to make first letter capital (in this case "c")
              <Component key={key}/>
          }
          

          另一种方法是像这样将组件包裹在div

          import React from 'react';
          export default [
              <ComponentOne/>
              <ComponentTwo/>
          ];
          // Then wrap in div
          {components.map((component, key) => (
              <div key={key}>
                {component}
              </div>
          }
          

          【讨论】:

          • 第二种方法行不通,因为你不能返回这样的东西&lt; &lt;Component/&gt;/&gt;
          • @TheReason 原因是什么?
          • 刚刚更新了一条评论,您必须从数组组件的元素中删除&lt; & /&gt;。有意义吗?
          【解决方案8】:

          如果您使用 16 以上的 react 版本,您可以像这样创建组件列表:

          import React from 'react';
          
          export const componentList = [ ComponentOne, ComponentTwo ];
          

          然后像这样在任何地方渲染它们:

          import React from 'react';
          
          function SomeComponent() {
            return (
              <div>
                {componentList.map((component, index) => (
                  <div key={index}> {component && component.render()}</div>
                ))}
              </div>
            );
          }
          

          【讨论】:

            【解决方案9】:

            如果我将组件放入数组中,我通常会这样做:

            const COMPONENTS = [
              <Foo />,
              <Bar />
            ]
            
            [0, 1].map(item => {
                  return (
                    <React.Fragment key={item}>
                      {COMPONENTS[item]}
                    </React.Fragment>
                  )
            })
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2020-12-12
              • 2017-03-08
              • 2015-11-16
              • 2017-12-16
              • 2020-03-22
              • 1970-01-01
              • 2019-11-07
              相关资源
              最近更新 更多