简体   繁体   English

反应 PropTypes - 或者

[英]React PropTypes - OR

For this code:对于这段代码:

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.");
}

In order to set the propTypes of MyComponent , is it possible to do something like:为了设置MyComponentpropTypes ,是否可以执行以下操作:

MyComponent.propTypes = FirstComponentPropTypes | SecondComponentPropTypes;

?

As you pointed out:正如您所指出的:

MyComponent is a "generic" component which renders A if foo is present or B if bar is present. MyComponent 是一个“通用”组件,如果存在 foo 则呈现 A,如果存在 bar 则呈现 B。

And it's definition is function MyComponent({ foo, bar }) {... }它的定义是function MyComponent({ foo, bar }) {... }

In order to avoid complex solutions, I suggest you to move the conditional logic outside of MyComponent .为了避免复杂的解决方案,我建议您将条件逻辑移到MyComponent之外。 In this way you will need a single propType definition for MyComponent without duplicating the propType definitions of the other two components.这样,您将需要 MyComponent 的单个 propType 定义,而无需复制其他两个组件的 propType 定义。 The type your component will check is element , a common type shared by all React's elements.您的组件将检查的类型是element ,这是所有 React 元素共享的通用类型。

MyComponent.propTypes = {
    elementToRender: PropTypes.element
};

So you need to adapt your component definition:所以你需要调整你的组件定义:

function MyComponent({ elementToRender }) { ... }

And the way it is used:以及它的使用方式:

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)

Your jsx:你的 jsx:

{!element && <YourErrorComponent />}
{element && <MyComponent elementToRender={element} />}

You can always put your conditional logic inside the component without using a constant or variable, if you want.如果需要,您始终可以在不使用常量或变量的情况下将条件逻辑放入组件中。

Benefits好处

The biggest benefit of this approach is that your MyComponent doesn't need to know anything about yours FirstComponent or SecondComponent types.这种方法的最大好处是您的MyComponent不需要了解您FirstComponentSecondComponent类型的任何信息。 And you can always choose to use another component to pass to MyComponent without changing it.并且您始终可以选择使用另一个组件传递给MyComponent而无需更改它。

Moreover, you have a single point in the code where types are defined and you don't have any dependencies between them.此外,您在定义类型的代码中只有一个点,并且它们之间没有任何依赖关系。

Also, you are not getting props in one point and then using them in a condition far away from it.此外,您不会在某一点获得道具,然后在远离它的条件下使用它们。

A final consideration最后的考虑

To keep you code easy to read, I suggest you to avoid using a specific prop for an element.为了让您的代码易于阅读,我建议您避免对元素使用特定的属性。 Use props.children instead:使用props.children代替:

    {element && <MyComponent>{element}</MyComponent>}

This is a more React-ish ( natural ) way to show a component inside another one: the children props exists to this purpose.这是一种更React 式自然)的方式来显示另一个组件内的组件: children props 就是为此目的而存在的。

Moreover, you can put (again) a fallback logic inside MyComponent:此外,您可以(再次)在 MyComponent 中放置一个回退逻辑:

function MyComponent({ children }) {
    if (children) {
        return <div className="container">{children}</div>
    }
    
    return <p>children is missing</>
}

I assume you mean |我假设你的意思是| as in you want to take the union of the two sets?比如你想把这两个集合结合起来? You can just merge the two objects with something like Object.assign():您可以将这两个对象与 Object.assign() 之类的东西合并:

const FirstComponentPropTypes = {
   foo: PropTypes.any,
};

const SecondComponentPropTypes = {
   bar: PropTypes.any,
};

function MyComponent({ foo, bar }) { ... }

MyComponent.propTypes = Object.assign({}, SecondComponentPropTypes, FirstComponentProptypes);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM