-
-
Save kitze/23d82bb9eb0baabfd03a6a720b1d637f to your computer and use it in GitHub Desktop.
import React from 'react'; | |
const ConditionalWrap = ({condition, wrap, children}) => condition ? wrap(children) : children; | |
const Header = ({shouldLinkToHome}) => ( | |
<div> | |
<ConditionalWrap | |
condition={shouldLinkToHome} | |
wrap={children => <a href="/">{children}</a>} | |
> | |
<img src="logo.png"/> | |
</ConditionalWrap> | |
</div> | |
) |
This fails if condition = false, and you are returning more than one child on React 15, if so I would change line 3 to
const ConditionalWrap = ({condition, wrap, children}) => condition ? wrap(children) : <div>children</div>;
This fails if condition = false, and you are returning more than one child on React 15, if so I would change line 3 to
const ConditionalWrap = ({condition, wrap, children}) => condition ? wrap(children) : <div>children</div>;
or even using new React Fragments
short syntax;
https://reactjs.org/docs/fragments.html#short-syntax
const ConditionalWrap = ({condition, wrap, children}) => condition ? wrap(children) : <>{children}</>;
Thanks for sharing the unit test! How would you test the ConditionalWrap if it is defined within component render(){}?
Can someone provide a typescript version for this?
This is what I have:
import React, { FunctionComponent } from 'react';
interface IConditionalWrapProps {
condition: boolean;
wrap: Function;
children: React.ReactNode;
}
const ConditionalWrap: FunctionComponent<IConditionalWrapProps> = ({
condition,
wrap,
children,
}) => (condition ? wrap(children) : <>{children}</>);
export default ConditionalWrap;
Please let me know if this suffices.
typescript version:
type ConditonalWrapperProps = {
children: React.ReactElement;
condition: boolean;
wrapper: (children: React.ReactElement) => JSX.Element;
};
const ConditonalWrapper: React.FC<ConditonalWrapperProps> = ({ condition, wrapper, children }) =>
condition ? wrapper(children) : children
@jensbodal thanks but the types are in the package already
an even better api, and the way i use it is:
<Wrap
if={someCondition}
with={ch => <View>{ch}</View>}
>
<Text />
</Wrap>
here we go, nice TS code
import React, { FC } from "react"
interface WrapProps {
if: boolean
with: (children: React.ReactNode) => JSX.Element
}
export const Wrap: FC<WrapProps> = ({ if: condition, with: wrapper, children }) => {
return condition ? wrapper(children) : <>children</>
}
@kitze Small question)) For what reasons React.cloneElement is used?
I have an improvement suggestion for this:
import { FC, ReactNode, createElement } from 'react';
interface WrapProps {
if?: boolean;
with: typeof createElement.arguments[0];
wrapperProps: typeof createElement.arguments[1];
children: NonNullable<ReactNode>;
}
const Wrap: FC<WrapProps> = ({
if: condition,
with: wrapper,
wrapperProps,
children,
}) =>
condition ? createElement(wrapper, wrapperProps, [children]) : <>children</>;
export default Wrap;
By using createElement
we can use Wrap like so:
<Wrap if={condition} with="a" wrapperProps={{ 'data-testid': 'wrapper' }}>
<p>Wrapped text</p>
</Wrap>
Instead of always passing a (children) => <jsx />
function.
FYI this function breaks the react/no-unstable-nested-components eslint rule.
Some Unit tests: