我有一个简单的 React 组件来包装它的 children
:
function Wrapper(props) {
return <div>{props.children}</div>;
}
如果我传递了一个无效的子组件,这个组件会抛出一个错误:
const plain_object = {};
// This throws an error
ReactDOM.render(<Wrapper>{plain_object}</Wrapper>, container);
我想要的是检查我传入的孩子是否会无错误地渲染,任何有效的“可渲染”值。例如:
function SafeWrapper(props) {
// Note, this function doesn't exist, but I want it to
if (!isValidChildren(props.children)) {
return null;
}
return <div>{props.children}</div>;
}
const plain_object = {};
// This will no longer throw
ReactDOM.render(<SafeWrapper>{plain_object}</SafeWrapper>, container);
我知道 React 有 React.isValidElement
,但这不会检查原始代码或任何其他可以正常渲染的项目:
// The following calls all return `false` despite them
// not throwing errors when you try and pass them in the `children` prop
// Note that not all of these will render (e.g. the falsy values are skipped)
// but they still don't throw.
React.isValidElement('');
React.isValidElement('Hello');
React.isValidElement(0);
React.isValidElement(1);
React.isValidElement(null);
React.isValidElement(undefined);
React.isValidElement([1]);
React.isValidElement([<div />]);
是否有我在示例中提到的 isValidChildren
函数?如果没有,写一个会是什么样子?
/**
* Returns `true` if `children` can be passed without throwing. `false` if otherwise.
*/
function isValidChildren(children) {
// ?
}
答案 0 :(得分:1)
你可以这样做:
const isRenderable = (node) => {
let renderable;
switch (typeof node) {
case "string":
case "number":
renderable = true;
break;
default:
if (Array.isArray(node) && node.length) {
renderable = node.reduce((acc, e) => acc && isRenderable(e), true);
break;
}
renderable = React.isValidElement(node);
break;
}
return renderable;
};
答案 1 :(得分:0)
它没有直接回答您关于实现要检查的函数的问题,但您可以使用带有内部空包装器的 ErrorBoundary
来处理不可渲染内容的情况:
class ErrorBoundary extends React.Component {
state = { error: null, errorInfo: null }
static getDerivedStateFromError(error, errorInfo) {
return { error, errorInfo }
}
render() {
if (this.state.error) {
return <span>something went wrong</span>
}
return this.props.children
}
}
// needed because the error boundary catches errors
// in *nested* components, whereas if it tried
// to render the children directly, it can't catch
// errors in its own `render`
const Inner = ({ children }) => children
const SafeWrapper = ({ children }) => (
<ErrorBoundary>
<Inner>{children}</Inner>
</ErrorBoundary>
)
也就是说,如果您试图在不知道它们是什么的情况下渲染事物,就会有一点代码异味。我无法想象您只想尝试在 DOM 上抛出随机值的用例。