首页 > 解决方案 > 确定组件是否是 React 中功能组件实例的最佳方法

问题描述

对于我正在构建的组件,我正在递归地循环其子组件React.Children.map,以对其道具进行修改。基本结构是这样的:

// 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将通过修改他们的道具recursivelyModifyChildProps,他们的孩子将修改他们的道具等。我想这样做,除非子组件是组件的实例Main,在这种情况下,它应该不加修改地返回。目前我正在通过 执行此child.type.name操作,这确实有效。然而,我相信这个实现很容易出错,因为每个人都可以称他们的组件为“Main”。什么是最好的(或至少更好的)方法来确定一个组件是一个实例,一个特定的(功能性)组件,还是它本身的一个实例?

标签: javascriptreactjsreact-propsreact-componentreact-functional-component

解决方案


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

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

编辑 Q-58851178-childType


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

推荐阅读