反应高阶组件警告
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()
电话
我在 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()
电话