Skip to content

Instantly share code, notes, and snippets.

@realamirhe
Last active March 14, 2024 08:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save realamirhe/b29cef9b00211db0c2611e340798a556 to your computer and use it in GitHub Desktop.
Save realamirhe/b29cef9b00211db0c2611e340798a556 to your computer and use it in GitHub Desktop.
Conditional Render in jsx
import { ReactNode } from 'react';
export const Main = ({ active }: { active: boolean }) => {
return <p>my component {active ? 'active' : 'de-active'}</p>;
};
export const Skeleton = ({ count }: { count: number }) => {
return <p>skeleton x{count}</p>;
};
export const ColorFull = ({
color,
children,
}: {
color: string;
children: ReactNode;
}) => {
return <p style={{ color }}>Text with color:={children}</p>;
};
/* eslint-disable @typescript-eslint/no-explicit-any */
import {
ReactNode,
RefAttributes,
cloneElement,
createElement,
isValidElement,
} from 'react';
export default function Z() {
const elementSymbols = Symbol('elements');
const fallbackSymbol = Symbol('fallback');
return {
[elementSymbols]: [] as ReactNode[],
[fallbackSymbol]: null as any,
__add(item: ReactNode) {
this[elementSymbols].push(item);
},
fallback(...args: any) {
this[fallbackSymbol] = args;
return this;
},
$: function $add<
TRenderer extends ((props: any, ref: any) => ReactNode) | ReactNode,
>(
condition: boolean,
renderer: TRenderer,
props?: TRenderer extends (
props: infer TProps,
ref?: unknown,
) => ReactNode
? TProps
: Record<string, unknown>,
ref?: TRenderer extends (props: unknown, ref?: infer TRef) => ReactNode
? TRef
: RefAttributes<unknown>,
) {
if (condition) {
this[elementSymbols].push(
this.__elementRetriever(renderer, props, ref),
);
}
return this;
},
__elementRetriever<
TRenderer extends ((props: any, ref: unknown) => ReactNode) | ReactNode,
>(
renderer: TRenderer,
props:
| (TRenderer extends (props: infer TProps, ref?: unknown) => ReactNode
? TProps
: Record<string, any>)
| undefined,
ref: RefAttributes<unknown> | undefined,
) {
if (isValidElement(renderer)) return cloneElement(renderer, props);
if (typeof renderer === 'function') return renderer(props, ref);
if (typeof renderer === 'string') {
if (props) return createElement(renderer, props);
return renderer;
}
},
[Symbol.iterator]: function* () {
if (!this[elementSymbols].length && this[fallbackSymbol]) {
yield this.__elementRetriever(
...(this[fallbackSymbol] as Parameters<
typeof this.__elementRetriever
>),
);
return;
}
for (const element of this[elementSymbols]) {
yield element;
}
},
};
}
import { ColorFull, Main, Skeleton } from './components.tsx';
import Z from './z.tsx';
export default function App() {
return Z()
.$(true, Main, { active: true }) // Will render <Main active={ture} />
.$(false, 'Hello text content') // Won't render this Text-Node
.$(true, 'h1', { // Will render <h1 {...props} />
'data-attr': 'my-attribute',
'data-source': null,
children: <ColorFull color="red">Hello Red Children</ColorFull>,
})
.$(true, <ColorFull color="yellow">Hello Yellow ELement</ColorFull>) // Will render the element
.fallback(Skeleton, { count: 3 });
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment