确定组件是否是 React 中功能组件实例的最佳方法

Best way to figure out if component is an instance of functional component in React

对于我正在构建的组件,我使用 React.Children.map 递归循环遍历其 child 组件以修改它们的道具。基本结构是这样的:

// main component
const Main = ({ children }) => recursivelyModifyChildProps(children);

// recursive function
function recursivelyModifyChildProps(children) {
  return React.Children.map(children, (child) => {
    // if no valid react element, just return it
    if (!React.isValidElement(child)) {
      return child;
    }

    // check if child isn't a `<Main/>` component
    // not sure about this check
    if (typeof child.type !== 'string' && child.type.name === 'Main') {
      return child;
    }

    const { children, ...restProps } = child.props;

    // do stuff to create new props
    const newProps = { foo: 'bar' };

    // return new element with modified props
    return React.createElement(
      child.type,
      {
        ...restProps,
        ...newProps,
        children: recursivelyModifyChildProps(children)
      }
    );

  });
}
Main

Children 将通过 recursivelyModifyChildProps 修改他们的道具,他们的 children 将修改他们的道具,等等。我想这样做,除非child 组件是 Main 组件的一个实例,在这种情况下,它应该原封不动地返回。目前我正在通过 child.type.name 执行此操作,这确实有效。但是,我认为这种实现很容易出错,因为每个人都可以调用他们的组件 "Main"。确定组件是特定(功能)组件的实例还是自身实例的最佳(或至少更好)方法是什么?

您可以通过比较 child.typeMain 实例来验证它是唯一的。

if (child.type === Main) {
  return undefined;
}


修改所有 Main 子级并跳过 Main 实例的完整示例。

import React from 'react';
import ReactDOM from 'react-dom';

const Main = ({ children }) => recursivelyModifyChildProps(children);

function recursivelyModifyChildProps(children) {
  return React.Children.map(children, child => {
    if (!React.isValidElement(child)) {
      return child;
    }

    if (child.type === Main) {
      return undefined;
    }

    const { children, ...restProps } = child.props;
    const newProps = { foo: 'bar' };

    return React.createElement(child.type, {
      ...restProps,
      ...newProps,
      children: recursivelyModifyChildProps(children)
    });
  });
}

const App = () => {
  return (
    <Main>
//       v Main is skipped
      <Main />
      <div>Hello</div>
    </Main>
  );
};

ReactDOM.render(<App />, document.getElementById('root'));