Skip to content

Instantly share code, notes, and snippets.

@MurylloEx
Last active October 17, 2024 14:02
Show Gist options
  • Save MurylloEx/b0b4552f74019424702bd796b20265d3 to your computer and use it in GitHub Desktop.
Save MurylloEx/b0b4552f74019424702bd796b20265d3 to your computer and use it in GitHub Desktop.
[React] If Conditional Render
import { Fragment, FunctionComponent, ReactElement, useCallback } from 'react';
import { IfElse } from './IfElse';
import { IfThen } from './IfThen';
import { IfElseIf } from './IfElseIf';
type CompoundComponent<T, K> = FunctionComponent<T> & K;
type IfThenType = typeof IfThen;
type IfElseType = typeof IfElse;
type IfElseIfType = typeof IfElseIf;
export type IfThenChildren = ReactElement<IfThenType>;
export type IfElseChildren = ReactElement<IfElseType>;
export type IfElseIfChildren = ReactElement<IfElseIfType>;
export type IfElseElseIfChildren = IfElseChildren | IfElseIfChildren;
export type IfThenElseChildren = [IfThenChildren, IfElseChildren];
export type IfThenElseElseIfChildren = [IfThenChildren, ...IfElseElseIfChildren[]];
export type IfChildren =
IfThenChildren |
IfElseChildren |
IfThenElseChildren |
IfThenElseElseIfChildren;
export interface IfCompound {
Then: IfThenType;
Else: IfElseType;
ElseIf: IfElseIfType;
}
export interface IfProps {
value: boolean;
children: IfChildren;
}
export const If: CompoundComponent<IfProps, IfCompound> = ({ children, value }) => {
const hasMultipleFlows = Array.isArray(children);
const getFlowResult = useCallback((desiredFlow: IfThenType | IfElseType | IfElseIfType) => {
if (hasMultipleFlows) {
const [thenFlow, ...elseFlows] = children;
if ((desiredFlow === IfThen) && (thenFlow.type === IfThen)) {
return thenFlow;
}
return elseFlows.reduce((accumulator: ReactElement | null, flow: IfElseElseIfChildren) => {
if (accumulator) {
return accumulator;
}
if (flow.type === desiredFlow) {
return flow.type(flow.props);
}
return accumulator;
}, null);
}
if ((desiredFlow === IfThen) && (children.type === IfThen)) {
return children;
}
if ((desiredFlow === IfElse) && (children.type === IfElse)) {
return children;
}
return <Fragment />;
}, [hasMultipleFlows, children, value]);
return value
? getFlowResult(IfThen)
: getFlowResult(IfElseIf)
?? getFlowResult(IfElse);
}
If.Then = IfThen;
If.Else = IfElse;
If.ElseIf = IfElseIf;
export * from './IfThen';
export * from './IfElse';
export * from './IfElseIf';
import { Fragment, FunctionComponent, ReactNode } from 'react';
export interface IfElseProps {
children: ReactNode;
}
export const IfElse: FunctionComponent<IfElseProps> = ({ children }) => {
return ( <Fragment>{children}</Fragment> );
}
import { Fragment, FunctionComponent, ReactNode } from 'react';
export interface IfElseIfProps {
value: boolean;
children: ReactNode;
}
export const IfElseIf: FunctionComponent<IfElseIfProps> = ({ value, children }) => {
return value ? <Fragment>{children}</Fragment> : null;
}
import { Fragment, FunctionComponent, ReactNode } from 'react';
export interface IfThenProps {
children: ReactNode;
}
export const IfThen: FunctionComponent<IfThenProps> = ({ children }) => {
return ( <Fragment>{children}</Fragment> );
}
import { Fragment, FunctionComponent } from 'react';
import { If } from './If';
export interface PageProps { }
export const Page: FunctionComponent<PageProps> = () => {
const value: number = 5;
return (
<Fragment>
<If value={value === 1}>
<If.Then>
<div>O número é o 1</div>
</If.Then>
<If.ElseIf value={value === 0}>
<div>O número é o 0</div>
</If.ElseIf>
<If.ElseIf value={value === 2}>
<div>O número é o 2</div>
</If.ElseIf>
<If.ElseIf value={value === 3}>
<div>O número é o 3</div>
</If.ElseIf>
<If.Else>
<div>O número não é nem 0, 1, 2 ou 3.</div>
</If.Else>
</If>
</Fragment>
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment