对于正在构建的组件,我正在使用React.Children.map递归地遍历其子组件以对其 Prop 进行修改。基本结构是这样的:

// 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修改其 Prop ,而他们的子代将对其 Prop 进行修改,依此类推。除非子组件是Main组件的实例,否则我想这样做,在这种情况下,应不加修改地返回它。目前,我正在通过child.type.name做到这一点,并且确实可以。但是,我相信此实现非常容易出错,因为每个人都可以将其组件称为“Main”。弄清某个组件是一个实例(特定的(功能)组件还是其实例)的最佳(或至少更好)的方法是什么?

最佳答案

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

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

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

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

08-06 03:42