访问反应元素的子元素

时间:2018-08-09 22:23:58

标签: javascript reactjs high-order-component

想象一下具有React组件

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

我想创建一个高阶组件,例如,修改所有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
                )
            )
        );
    }
}

但是。这行不通。孩子们是空的。

有趣的是,如果我直接创建组件,例如

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

问题:如何访问任何React元素的子孙?

1 个答案:

答案 0 :(得分:1)

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

说,这是您的用例的一个实用示例-https://codesandbox.io/s/ymqwyww22z

基本上,这是我所做的:

  1. 使List为基于类的组件。将功能组件包装到一个组件中并没有太大的麻烦。

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

    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);
        }
      };
    }
    

createElement的{​​{1}}版本有何不同?

makeRed返回一个HOC时,在makeRed组件中使用它时,您无需为其分配道具。像这样...

App

因此在动态组件函数中,您使用function App() { return <RedList />; // no props! } 创建新实例的过程中,createElement不会携带任何子代。由于component.props创建了自己的子代,因此您需要获取并修改它们,而不是从List读取子代。

相关问题