Created
January 6, 2025 12:54
-
-
Save GeorgeCht/0bfccd0189b8c14abd1a108674528cce to your computer and use it in GitHub Desktop.
SolidJS Utility Components in React
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Renders a list of items from an array. If the array is empty, renders the | |
* `fallback` if provided. | |
* | |
* @param {Array<T>} each The array of items to render. | |
* @param {ReactNode} fallback An optional element to render if the array is empty. | |
* @param {(item: T, index: number) => U} children A function that takes an item and its index and returns a React element. | |
* | |
* @example | |
* ```tsx | |
* // π₯± pure jsx | |
* {items.length > 0 | |
* ? items.map((item, index) => <Item key={index} item={item} />) | |
* : <div>No items</div> | |
* } | |
* | |
* // π with <For /> | |
* <For each={items} fallback={<div>No items</div>}> | |
* {(item, index) => <Item key={index} item={item} />} | |
* </For> | |
* ``` | |
*/ | |
export function For<T, U extends React.ReactNode>(props: { | |
each: Array<T> | |
fallback?: React.ReactNode | undefined | |
children: (item: T, index: number) => U | |
}): React.ReactElement { | |
return ( | |
<React.Fragment> | |
{props.each | |
? props.each.map((item, index) => props.children(item, index)) | |
: props.fallback} | |
</React.Fragment> | |
) | |
} | |
/** | |
* Conditionally renders the given children if the `when` prop is truthy. | |
* | |
* If the `when` prop is falsy, renders the `fallback` prop instead if it is | |
* provided. | |
* | |
* If the `children` prop is a function, it is called with the value of the | |
* `when` prop as its argument. Otherwise, the `children` prop is rendered | |
* directly. | |
* | |
* Similar to the ternary operator `when ? children : fallback` but ideal for templating JSX. | |
* | |
* @param {T | undefined | null | false} when The condition to evaluate. | |
* @param {ReactNode} fallback An optional element fallback. | |
* @param {ReactNode | ((item: T) => ReactNode)} children The element to render if `when` is truthy. | |
* | |
* @example | |
* ```tsx | |
* // π₯± pure jsx | |
* {condition ? <True /> : <False />} | |
* | |
* // π with <Show /> | |
* <Show when={condition} fallback={<False />}> | |
* <True /> | |
* </Show> | |
* | |
* // π keying with <Show /> | |
* <Show when={session.user} fallback={<div>Not logged in</div>}> | |
* {(user) => <div>Hello, {user.name}</div>} | |
* </Show> | |
* ``` | |
*/ | |
export function Show<T>(props: { | |
when: T | undefined | null | false | |
fallback?: React.ReactNode | undefined | |
children: React.ReactNode | ((item: T) => React.ReactNode) | |
}): React.ReactElement { | |
return ( | |
<React.Fragment> | |
{props.when | |
? typeof props.children === 'function' | |
? props.children(props.when) | |
: props.children | |
: props.fallback} | |
</React.Fragment> | |
) | |
} | |
/** | |
* Conditionally renders the given children if the `when` prop is truthy. | |
* | |
* If the `children` prop is a function, it is called with the value of the | |
* `when` prop as its argument. Otherwise, the `children` prop is rendered | |
* directly. | |
* | |
* @param {T | undefined | null | false} when The condition to evaluate. | |
* @param {ReactNode | ((item: T) => ReactNode)} children The element to render if `when` is truthy. | |
*/ | |
export function Match<T>(props: { | |
when: T | undefined | null | false | |
children: React.ReactNode | ((item: T) => React.ReactNode) | |
}): React.ReactElement | null { | |
if (!props.when) return null | |
return ( | |
<React.Fragment> | |
{typeof props.children === 'function' | |
? props.children(props.when) | |
: props.children} | |
</React.Fragment> | |
) | |
} | |
/** | |
* Conditionally renders the first {@link Match} child with a truthy `when` prop. | |
* | |
* If none of the {@link Match} children have a truthy `when` prop, renders the | |
* `fallback` prop if it is provided. | |
* | |
* @param {ReactNode} children The children to evaluate, expected to be {@link Match} elements. | |
* @param {ReactNode} fallback An optional element to render if no {@link Match} children have a truthy `when` prop. | |
* | |
* @example | |
* ```tsx | |
* // π₯± pure jsx | |
* if (route === "home") { | |
* return <div>Home</div> | |
* } | |
* if (route === "settings") { | |
* return <div>Settings</div> | |
* } | |
* return <div>Not found</div> | |
* | |
* // π with <Switch /> | |
* <Switch fallback={<div>Not found</div>}> | |
* <Match when={route === "home"}> | |
* <Home /> | |
* </Match> | |
* <Match when={route === "settings"}> | |
* <Settings /> | |
* </Match> | |
* </Switch> | |
* ``` | |
*/ | |
export function Switch(props: { | |
fallback?: React.ReactNode | |
children: | |
| React.ReactElement<typeof Match> | |
| Array<React.ReactElement<typeof Match>> | |
}): React.ReactElement { | |
const match: React.ReactNode | undefined = React.Children.toArray( | |
props.children, | |
).find((child) => { | |
if (React.isValidElement(child) && child.type === Match) { | |
return child.props.when | |
} | |
return false | |
}) | |
return ( | |
<React.Fragment> | |
{match && React.isValidElement(match) ? match : props.fallback} | |
</React.Fragment> | |
) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment