首页 > 解决方案 > React - 基于 API 响应渲染动态组件

问题描述

感谢您花时间阅读本文。

我是 React 的新手,我在动态渲染组件方面有些吃力。从 API 接收的对象可以任意嵌套到 x 个级别,需要注入的组件名称是从 BE 接收的。

我从 API 得到响应,看起来像这样:

{
  name: 'div'
  components: [
    componentOne: {
      name: 'div'
      components: [
        {
          name: 'p',
          components: [...deeply nested]
        },
        {
          name: 'h1',
          components: [...deeply nested]
        }
      ]
    }
    componentTwo: {
      name: 'nav',
      components: [...]
    }
  ] 
}

标签: reactjs

解决方案


您将不得不处理不同类型的节点(至少是文本),但这只是沿着树(API 响应)走并根据它构建 React 节点树的问题:

所以你的节点定义看起来像这样(这是伪语法,并不意味着在你的代码中):

    node: {
        type: 'element' | 'text' => the type will be needed,
        name: string => a tag name (if it is a React element),
        children: node[]
    }

因此,您的 api 的实际响应可能是:

    {
        type: 'element',
        name: 'div',
        children: [
            {
                type: 'element',
                name: 'div',
                children: [
                    {
                        type: 'element',
                        name: 'h1',
                        children: [
                            { type: 'text', value: 'Title 1' }
                        ]
                    },
                    {
                        type: 'element',
                        name: 'p',
                        children: [
                            { type: 'text', value: 'This is a paragraph' }
                        ]
                    }
                ]
            },
            {
                type: 'element',
                name: 'nav',
                children: []
            }
        ]

    }

我们将把这个解析为对象的响应传递给 generateTreeNode 方法:

    /**
     * @param {object} apiResponse
     * @returns {ReactNode}
     */
    function generateTreeNode(apiResponse) {
        switch (apiResponse.type) {
            case 'element':
                return React.createElement(apiResponse.name, { children: apiResponse.children.map(child => generateTreeNode(child)) });
            case 'text':
                return apiResponse.value;
            default: // no default
        }
    }

请注意,递归调用将确保遍历整个 apiResponse 树。

就是这样。这是未经测试的,但应该可以很好地工作:generateTreeNode 函数的返回值可以用作渲染方法的返回值。

您应该了解使用它的主要资源是什么是 React Node创建一个 react node

此外,请随意(并且您应该)扩展您的 api 响应结构并步行处理:

  • 自定义组件(您必须以某种方式导入)
  • 附加元素道具(例如样式或类名)
  • ETC...

另请注意,此代码假定您的响应的根是一个节点(请记住 React 不允许您在渲染方法中一次返回多个节点,数组和片段除外,这就是原因)


推荐阅读