访问 React 元素的 children

Access children of react element

想象一下有 React 组件

function List() {
   return (<ul>
             <li>1</li>
             <li>2</li>
           </ul>
    );
}

我想创建 high-order 组件来修改,例如,所有 li 节点的样式。

function makeRed(component) {
    return function(props) {
         const element = React.createElement(component, props);

         return React.cloneElement(
            element,
            element.props,
            React.Children.map(
                element.props.children,
                ch => React.cloneElement(ch, { 
                        ...ch.props, 
                        style: {
                           backgroundColor: "red"
                        }
                    },                    
                    ch.props.children
                )
            )
        );
    }
}

但是。这是行不通的。 Children 为空。

有趣的是,如果我直接创建组件,这会起作用,比如

...    
const element = <ul><li>1</li><li>2</li></ul>;
...

问题:如何访问任何 React 元素的 children 和 grandchildren?

正如@hamms 指出的那样,这是一种反模式。有 better ways to implement themes in React 使用普通的旧 CSS。

也就是说,这是对您的用例的一个有效示例的 hack - https://codesandbox.io/s/ymqwyww22z

基本上,这是我所做的:

  1. 使 List 成为基于 class 的组件。把一个功能组件包装成一个也不嫌麻烦

    import React, { Component } from "react";
    
    export default class List extends Component {
      render() {
        return (
          <ul>
            <li>1</li>
            <li>2</li>
          </ul>
        );
      }
    }
    
  2. 在动态 class Red<Component> 中实现 render 以首先获取从基本组件的渲染返回的元素树,然后对其进行编辑。

    import React from "react";
    
    export default function makeRed(Component) {
      return class RedComponent extends Component {
        constructor(props) {
          super(props);
    
          RedComponent.displayName = `Red${Component.name}`;
        }
    
        render() {
          let componentElement = super.render();
          let { children, ...rest } = componentElement.props;
          children = React.Children.map(children, child => {
            return React.cloneElement(child, {
              ...child.props,
              style: {
                backgroundColor: "red"
              }
            });
          });
          return React.cloneElement(componentElement, rest, ...children);
        }
      };
    }
    

这与 makeRedcreateElement 版本有何不同?

作为 makeRed returns 一个 HOC,当你在你的 App 组件中使用它时,你不会为它分配道具。像这样...

function App() {
  return <RedList />; // no props!
}

因此在动态组件函数中,您使用 createElement 创建新实例的地方,component.props 不携带任何子项。由于 List 创建了自己的子项,因此您需要获取并修改它们,而不是从 props.

中读取子项