反应 PropTypes - 或者
React PropTypes - OR
对于此代码:
const FirstComponentPropTypes = {
foo: PropTypes.any,
};
const SecondComponentPropTypes = {
bar: PropTypes.any,
};
...
function MyComponent({ foo, bar }) {
if (foo) {
return <FirstComponent foo={foo} />;
} else if (bar) {
return <SecondComponent bar={bar} />;
}
throw new Error("Invalid props.");
}
为了设置 MyComponent
的 propTypes
,是否可以这样做:
MyComponent.propTypes = FirstComponentPropTypes | SecondComponentPropTypes;
?
我假设您的意思是 |
是因为您想对这两个集合求并集?您可以将这两个对象合并为 Object.assign():
const FirstComponentPropTypes = {
foo: PropTypes.any,
};
const SecondComponentPropTypes = {
bar: PropTypes.any,
};
function MyComponent({ foo, bar }) { ... }
MyComponent.propTypes = Object.assign({}, SecondComponentPropTypes, FirstComponentProptypes);
正如您所指出的:
MyComponent is a "generic" component which renders A if foo is present or B if bar is present.
它的定义是function MyComponent({ foo, bar }) { ... }
为了避免复杂的解决方案,我建议您将条件逻辑移到 MyComponent
之外。这样,您将需要 MyComponent 的单个 propType 定义,而无需复制其他两个组件的 propType 定义。您的组件将检查的类型是 element
,这是所有 React 元素共享的通用类型。
MyComponent.propTypes = {
elementToRender: PropTypes.element
};
因此您需要调整您的组件定义:
function MyComponent({ elementToRender }) { ... }
及其使用方式:
const getComponentToRender = (foo, bar) => {
if (foo) {
return <FirstComponent foo={foo} />;
} else if (bar) {
return <SecondComponent bar={bar} />;
} else {
return null;
}
}
const element = getComponentToRender(foo, bar)
你的 jsx:
{!element && <YourErrorComponent />}
{element && <MyComponent elementToRender={element} />}
如果需要,您始终可以在不使用常量或变量的情况下将条件逻辑放入组件中。
好处
这种方法的最大好处是您的 MyComponent
不需要了解您的 FirstComponent
或 SecondComponent
类型的任何信息。并且您始终可以选择使用另一个组件传递给 MyComponent
而无需更改它。
此外,您在定义类型的代码中只有一个点,它们之间没有任何依赖关系。
另外,你也不是在一个点上获得道具,然后在远离它的情况下使用它们。
最后的考虑
为了让您的代码易于阅读,我建议您避免对元素使用特定的 prop。使用 props.children
代替:
{element && <MyComponent>{element}</MyComponent>}
这是一种更React-ish(自然)的方式来显示另一个组件内的组件:children
道具就是为了这个目的而存在的。
此外,您可以(再次)在 MyComponent 中放置回退逻辑:
function MyComponent({ children }) {
if (children) {
return <div className="container">{children}</div>
}
return <p>children is missing</>
}
对于此代码:
const FirstComponentPropTypes = {
foo: PropTypes.any,
};
const SecondComponentPropTypes = {
bar: PropTypes.any,
};
...
function MyComponent({ foo, bar }) {
if (foo) {
return <FirstComponent foo={foo} />;
} else if (bar) {
return <SecondComponent bar={bar} />;
}
throw new Error("Invalid props.");
}
为了设置 MyComponent
的 propTypes
,是否可以这样做:
MyComponent.propTypes = FirstComponentPropTypes | SecondComponentPropTypes;
?
我假设您的意思是 |
是因为您想对这两个集合求并集?您可以将这两个对象合并为 Object.assign():
const FirstComponentPropTypes = {
foo: PropTypes.any,
};
const SecondComponentPropTypes = {
bar: PropTypes.any,
};
function MyComponent({ foo, bar }) { ... }
MyComponent.propTypes = Object.assign({}, SecondComponentPropTypes, FirstComponentProptypes);
正如您所指出的:
MyComponent is a "generic" component which renders A if foo is present or B if bar is present.
它的定义是function MyComponent({ foo, bar }) { ... }
为了避免复杂的解决方案,我建议您将条件逻辑移到 MyComponent
之外。这样,您将需要 MyComponent 的单个 propType 定义,而无需复制其他两个组件的 propType 定义。您的组件将检查的类型是 element
,这是所有 React 元素共享的通用类型。
MyComponent.propTypes = {
elementToRender: PropTypes.element
};
因此您需要调整您的组件定义:
function MyComponent({ elementToRender }) { ... }
及其使用方式:
const getComponentToRender = (foo, bar) => {
if (foo) {
return <FirstComponent foo={foo} />;
} else if (bar) {
return <SecondComponent bar={bar} />;
} else {
return null;
}
}
const element = getComponentToRender(foo, bar)
你的 jsx:
{!element && <YourErrorComponent />}
{element && <MyComponent elementToRender={element} />}
如果需要,您始终可以在不使用常量或变量的情况下将条件逻辑放入组件中。
好处
这种方法的最大好处是您的 MyComponent
不需要了解您的 FirstComponent
或 SecondComponent
类型的任何信息。并且您始终可以选择使用另一个组件传递给 MyComponent
而无需更改它。
此外,您在定义类型的代码中只有一个点,它们之间没有任何依赖关系。
另外,你也不是在一个点上获得道具,然后在远离它的情况下使用它们。
最后的考虑
为了让您的代码易于阅读,我建议您避免对元素使用特定的 prop。使用 props.children
代替:
{element && <MyComponent>{element}</MyComponent>}
这是一种更React-ish(自然)的方式来显示另一个组件内的组件:children
道具就是为了这个目的而存在的。
此外,您可以(再次)在 MyComponent 中放置回退逻辑:
function MyComponent({ children }) {
if (children) {
return <div className="container">{children}</div>
}
return <p>children is missing</>
}