反应高阶组件警告

React Higher Order Component Warning

我在 React 中使用 HOC 来限制对组件的访问,但我收到以下警告:validateDOMNesting(...): cannot appear as a descendant of . HOC 的完整代码(根据要求)如下:

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';

import * as selectors from '../../store/selectors';

class AccessRestrictedComponent extends Component {
  static propTypes = {
    auth: PropTypes.object.isRequired,
    mode: PropTypes.string.isRequired,

    useWithList: PropTypes.bool,
    checkItem: PropTypes.bool,

    restrictByRole: PropTypes.bool,
    restrictByMode: PropTypes.bool,
    allowedRoles: PropTypes.array,
    allowedModes: PropTypes.array,
    children: PropTypes.node.isRequired,
  };

  static defaultProps = {
    useWithList: false,
    checkItem: null,
    restrictByRole: false,
    restrictByMode: false,
    allowedRoles: [],
    allowedModes: [],
  };

  render() {
    const { auth, mode, restrictByRole, restrictByMode, allowedRoles, allowedModes, useWithList, checkItem } = this.props;
    const { role } = auth;

    if (useWithList && !checkItem) {
      return  (React.cloneElement(this.props.children, { ...this.props }));
    }

    if (restrictByRole && restrictByMode) {
      // console.log('restricting role and mode ');
      if (allowedRoles.includes(role) && allowedModes.includes(mode)) {
        // console.log(`role: ${role} and mode: ${mode} allowed.`);
        return (React.cloneElement(this.props.children, { ...this.props }));
      } return null;
    }
    if (restrictByRole) {
      // console.log('restricting role ');
      if (allowedRoles.includes(role)) {
        // console.log(`role: ${role} allowed.`);
        return (React.cloneElement(this.props.children, { ...this.props }));
      } return null;
    }
    if (restrictByMode) {
      // console.log('restricting mode ');
      if (allowedModes.includes(mode)) {
        // console.log(`${mode} allowed.`);
        return (React.cloneElement(this.props.children, { ...this.props }));
      } return null;
    }
    // console.log('component unrestricted');
    return (React.cloneElement(this.props.children, { ...this.props }));
  }
}

const mapStateToProps = state => ({
  state,
  auth: selectors.getAuth(state),
  mode: selectors.getMode(state),
});



export default  connect(mapStateToProps)(AccessRestrictedComponent);


我包装的组件是样式化组件 NavButton。我这样使用 HOC:

<AccessRestrictedComponent restrictByRole allowedRoles={[userRoles.ADMIN]}>
  <NavButton onClick={() => this.setState({ set: true })}>
    <Icon className="material-icons md-48" color={color}>{'wallpaper'}</Icon>
  </NavButton>
</AccessRestrictedComponent>

样式组件是这样的:

export const NavButton = styled.button`
  display:flex;
  align-content:flex-end;
  align-self:flex-end;
  background: none;
  border: none;
  &:hover,
  &:focus{
    ${Icon}{
      cursor: pointer;
      color: ${props => props.theme.theme === themeTypes.LIGHT ? colors.SLATE_BLUE_50 : colors.lightBlue};
      border-radius: 4px;
      outline: none;
      background: linear-gradient(${colors.shuttleGrey}, ${colors.shuttleGrey}) padding-box,
                  repeating-linear-gradient(-45deg,
                    ${colors.submarine} 0, ${colors.submarine} 25%, transparent 0, transparent 50%
                  ) 0 / 8px 8px;
    }
  }
`;

我不理解这个警告,因为我没有嵌套按钮,但是当我使用开发工具检查 UI 时,发现嵌套了两个按钮。有谁知道这可能是什么原因造成的?它是样式组件吗? HOC,也许还有别的东西?我想一个简单的解决方案是将样式组件更改为按钮以外的其他内容,但我认为这应该是有效代码。无论如何,非常感谢任何建议。

发生错误是因为当您克隆元素时,您将 children 作为道具传递给克隆的 child。因此,您的 parent 克隆了 button 并将另一个按钮作为道具发送到您的克隆按钮。

修复很简单,不要将 children 作为合并的 props 发送。

render() {
  const { children, ...rest } = this.props;
  // ...rest
  return React.cloneElement(children, { ...rest });

  //...rest
}

这样您就不会再将 children 作为 props 发送给 children

注意:您应该更换所有 React.cloneElement() 电话