React - 如何确定特定子组件是否存在?
React - how to determine if a specific child component exists?
如果我有这个结构:
const MyComponent = (props) => {
return (
<Wrapper />{props.children}</Wrapper>
);
}
我是这样使用它的:
<MyComponent>
<SomeInnerComponent />
</MyComponent>
如何从 MyComponent
函数中检查 <SomeInnerComponent />
是否明确包含在 <MyComponent></MyComponent>
之间?
鉴于您要检查 SomeInnerComponent
是否作为 child 存在,您可以执行以下操作
const MyComponent = (props) => {
for (let child in props.children){
if (props.children[child].type.displayName === 'SomeInnerComponent'){
console.log("SomeInnerComponent is present as a child");
}
}
return (
<Wrapper />{props.children}</Wrapper>
);
}
或者您可以对您的组件进行 propTypes 验证
MyComponent.propTypes: {
children: function (props, propName, componentName) {
var error;
var childProp = props[propName];
var flag = false;
React.Children.forEach(childProp, function (child) {
if (child.type.displayName === 'SomeInnerComponent') {
flag = true
}
});
if(flag === false) {
error = new Error(componentName + ' does not exist!'
);
}
return error;
}
},
只是想为类似但不同的需求提供一个答案,您可能有一个 HOC 包装了几层组件,并且您想看看 HOC 是否已经包装了一个组件。我想出的方法是让 HOC 在组件上添加一个数据属性作为标志,然后 HOC 可以在后续运行中检查它。
const WithFoo = Component = props => {
return props["data-with-foo"]
? <Component {...props} />
: (
<FooWrapper>
<Component {...props} data-with-foo />
</FooWrapper>
);
};
React 节点有一个 type
属性 设置为构造函数,或创建节点的函数。所以我写了下面的函数来检查一个React节点是否是由某个组件创建的。
const reactNodeIsOfType = (node, type) =>
typeof node === "object" && node !== null && node.type === type;
用法:
const MyComponent = (props) => {
let hasInnerComponent = false;
React.Children.forEach(props.children, (child) => {
if (reactNodeIsOfType(child, SomeInnerComponent)) {
hasInnerComponent = true;
}
});
return (
<>
<div>hasInnerComponent: {hasInnerComponent ? "yes" : "no"}.</div>
<Wrapper>{props.children}</Wrapper>
</>
);
}
<MyComponent><div /></MyComponent>
// hasInnerComponent: no
<MyComponent><SomeInnerComponent /></MyComponent>
// hasInnerComponent: yes
const c = <SomeInnerComponent />;
console.log(reactNodeIsOfType(c, SomeInnerComponent));
// true
这是 TypeScript 版本。调用它还会将正确的类型分配给节点的 props
.
const isObject = <T extends object>(value: unknown): value is T =>
typeof value === "object" && value !== null;
const reactNodeIsOfType = <
P extends object,
T extends { (props: P): React.ReactElement | null | undefined }
>(
node: React.ReactNode,
type: T
): node is { key: React.Key | null; type: T; props: Parameters<T>[0] } =>
isObject<React.ReactElement>(node) && node.type === type;
如果我有这个结构:
const MyComponent = (props) => {
return (
<Wrapper />{props.children}</Wrapper>
);
}
我是这样使用它的:
<MyComponent>
<SomeInnerComponent />
</MyComponent>
如何从 MyComponent
函数中检查 <SomeInnerComponent />
是否明确包含在 <MyComponent></MyComponent>
之间?
鉴于您要检查 SomeInnerComponent
是否作为 child 存在,您可以执行以下操作
const MyComponent = (props) => {
for (let child in props.children){
if (props.children[child].type.displayName === 'SomeInnerComponent'){
console.log("SomeInnerComponent is present as a child");
}
}
return (
<Wrapper />{props.children}</Wrapper>
);
}
或者您可以对您的组件进行 propTypes 验证
MyComponent.propTypes: {
children: function (props, propName, componentName) {
var error;
var childProp = props[propName];
var flag = false;
React.Children.forEach(childProp, function (child) {
if (child.type.displayName === 'SomeInnerComponent') {
flag = true
}
});
if(flag === false) {
error = new Error(componentName + ' does not exist!'
);
}
return error;
}
},
只是想为类似但不同的需求提供一个答案,您可能有一个 HOC 包装了几层组件,并且您想看看 HOC 是否已经包装了一个组件。我想出的方法是让 HOC 在组件上添加一个数据属性作为标志,然后 HOC 可以在后续运行中检查它。
const WithFoo = Component = props => {
return props["data-with-foo"]
? <Component {...props} />
: (
<FooWrapper>
<Component {...props} data-with-foo />
</FooWrapper>
);
};
React 节点有一个 type
属性 设置为构造函数,或创建节点的函数。所以我写了下面的函数来检查一个React节点是否是由某个组件创建的。
const reactNodeIsOfType = (node, type) =>
typeof node === "object" && node !== null && node.type === type;
用法:
const MyComponent = (props) => {
let hasInnerComponent = false;
React.Children.forEach(props.children, (child) => {
if (reactNodeIsOfType(child, SomeInnerComponent)) {
hasInnerComponent = true;
}
});
return (
<>
<div>hasInnerComponent: {hasInnerComponent ? "yes" : "no"}.</div>
<Wrapper>{props.children}</Wrapper>
</>
);
}
<MyComponent><div /></MyComponent>
// hasInnerComponent: no
<MyComponent><SomeInnerComponent /></MyComponent>
// hasInnerComponent: yes
const c = <SomeInnerComponent />;
console.log(reactNodeIsOfType(c, SomeInnerComponent));
// true
这是 TypeScript 版本。调用它还会将正确的类型分配给节点的 props
.
const isObject = <T extends object>(value: unknown): value is T =>
typeof value === "object" && value !== null;
const reactNodeIsOfType = <
P extends object,
T extends { (props: P): React.ReactElement | null | undefined }
>(
node: React.ReactNode,
type: T
): node is { key: React.Key | null; type: T; props: Parameters<T>[0] } =>
isObject<React.ReactElement>(node) && node.type === type;