如何构建一个了解其子项的高阶组件
How to build a High-Order Component that has knowledge of it's children
我想创建一个 High-Order Component 来处理它的子项根据传递的 permissions
属性 进行渲染的方式。
这是我现在拥有的:
import React from "react";
const PERMISSION_VIEW = 1;
const PERMISSION_EDIT = 1 << 1;
// A High-Order Component that adds visual feedback according to the
// permissions prop that gets passed to it
function withPermissions(Component) {
const wrapper = (props, ref) => {
const { permissions } = props;
// Do not apply any permissions handling if we don't
// pass any permissions
if (permissions === undefined) {
return <Component {...props} forwardedRef={ref} />;
}
const propChanges = [];
let afterElements = [];
if ((permissions & PERMISSION_VIEW) === 0) {
// We'll assume that the data is already filtered from the server
afterElements.push(
<span key={0}>You do not have permissions to view this field</span>
);
}
if ((permissions & PERMISSION_EDIT) === 0) {
afterElements.push(
<span key={1}>You do not have permissions to edit this field</span>
);
propChanges.push({ readOnly: true, disabled: true });
}
props = Object.assign({}, props, ...propChanges);
return (
<React.Fragment>
<Component {...props} forwardedRef={ref} /> {afterElements}
</React.Fragment>
);
};
// Give this component a more helpful display name in DevTools.
// e.g. "ForwardRef(logProps(MyComponent))"
const name = Component.displayName || Component.name;
wrapper.displayName = `withPermissions(${name})`;
return React.forwardRef(wrapper);
}
这是一个使用示例
function Data(props) {
return props.value || "";
}
Data = withPermissions(Data);
const ref = React.createRef();
const App = () => <Data permissions={0} ref={ref} value="111" />;
console.log(App);
ReactDOM.render(<App />, document.getElementById("root"));
这 is working 但是我想做的是根据组件的类型有额外的行为
- 例如,如果它是一个
input
元素并且没有编辑权限,则将字段设置为 readonly
- 如果它是
textarea
元素并且没有查看权限,则将字段设置为 readonly
- 如果它是 link 并且没有查看权限,请删除它的
href
道具
等...
这件事有可能吗?有没有更好的方法来解决这个问题?
您应该像下面这样传递条件 属性:
<input type="text" readonly={props.value && PERMISSION_EDIT} />
所以现在,如果用户没有 PERMISSION_EDIT
,那么 readonly
就会在那里。
感谢 @dfsq 澄清位运算符。
刚刚意识到我想错了。以不同方式处理它的包装控制器不应该是 HOC 的工作。包装的组件应该与 HOC 的 'interface' 兼容。
所以我做了什么:
按原样离开 HOC。
确保我用 HOC 包装的所有组件都处理它们的 readOnly 和 disabled 道具,但没有权限知识。
如果 JS 是一种类型化语言,我也会为此创建一个接口,但现在必须这样做:)
我想创建一个 High-Order Component 来处理它的子项根据传递的 permissions
属性 进行渲染的方式。
这是我现在拥有的:
import React from "react";
const PERMISSION_VIEW = 1;
const PERMISSION_EDIT = 1 << 1;
// A High-Order Component that adds visual feedback according to the
// permissions prop that gets passed to it
function withPermissions(Component) {
const wrapper = (props, ref) => {
const { permissions } = props;
// Do not apply any permissions handling if we don't
// pass any permissions
if (permissions === undefined) {
return <Component {...props} forwardedRef={ref} />;
}
const propChanges = [];
let afterElements = [];
if ((permissions & PERMISSION_VIEW) === 0) {
// We'll assume that the data is already filtered from the server
afterElements.push(
<span key={0}>You do not have permissions to view this field</span>
);
}
if ((permissions & PERMISSION_EDIT) === 0) {
afterElements.push(
<span key={1}>You do not have permissions to edit this field</span>
);
propChanges.push({ readOnly: true, disabled: true });
}
props = Object.assign({}, props, ...propChanges);
return (
<React.Fragment>
<Component {...props} forwardedRef={ref} /> {afterElements}
</React.Fragment>
);
};
// Give this component a more helpful display name in DevTools.
// e.g. "ForwardRef(logProps(MyComponent))"
const name = Component.displayName || Component.name;
wrapper.displayName = `withPermissions(${name})`;
return React.forwardRef(wrapper);
}
这是一个使用示例
function Data(props) {
return props.value || "";
}
Data = withPermissions(Data);
const ref = React.createRef();
const App = () => <Data permissions={0} ref={ref} value="111" />;
console.log(App);
ReactDOM.render(<App />, document.getElementById("root"));
这 is working 但是我想做的是根据组件的类型有额外的行为
- 例如,如果它是一个
input
元素并且没有编辑权限,则将字段设置为readonly
- 如果它是
textarea
元素并且没有查看权限,则将字段设置为readonly
- 如果它是 link 并且没有查看权限,请删除它的
href
道具 等...
这件事有可能吗?有没有更好的方法来解决这个问题?
您应该像下面这样传递条件 属性:
<input type="text" readonly={props.value && PERMISSION_EDIT} />
所以现在,如果用户没有 PERMISSION_EDIT
,那么 readonly
就会在那里。
感谢 @dfsq 澄清位运算符。
刚刚意识到我想错了。以不同方式处理它的包装控制器不应该是 HOC 的工作。包装的组件应该与 HOC 的 'interface' 兼容。
所以我做了什么: 按原样离开 HOC。 确保我用 HOC 包装的所有组件都处理它们的 readOnly 和 disabled 道具,但没有权限知识。
如果 JS 是一种类型化语言,我也会为此创建一个接口,但现在必须这样做:)