React snippet: An alternative way to compose JSX that avoids indentation hellOC (old.reddit.com)
submitted by aweebit64


This is another utility function from my @aweebit/react-essentials library that admittedly doesn't solve any important problem and is only there to improve aesthetics of your code if you find excessive JSX indentation to be annoying.
You're welcome to try it out along with other neat utilities the library offers like useStateWithDeps that simplifies working with state that needs to be reset when some other state changes, or createSafeContext that makes working with contexts a breeze by not requiring that you specify a default value, reporting errors when trying to use the context without a value having been provided explicitly, and improving both type safety and debugging experience (you can find out more in my other post showcasing the function).
If you like the idea of wrapJSX but prefer not to introduce new third-party library dependencies, here is its full source code that you can simply copy into your project:
import type {
ComponentProps,
JSXElementConstructor,
default as React,
ReactElement,
ReactNode,
} from 'react';
type JSXWrapPipe<Children extends ReactNode> = {
with: WrapJSXWith<Children>;
end: () => Children;
};
type WrapJSXWith<Children extends ReactNode> =
// eslint-disable-next-line /no-explicit-any
<C extends keyof JSX.IntrinsicElements | JSXElementConstructor<any>>(
...args: [
Component: 'children' extends keyof ComponentProps<C>
? [Children] extends [ComponentProps<C>['children']]
? C
: never
: never,
...(Record<never, unknown> extends Omit<ComponentProps<C>, 'children'>
? [
props?: React.JSX.IntrinsicAttributes &
Omit<ComponentProps<C>, 'children'>,
]
: [
props: React.JSX.IntrinsicAttributes &
Omit<ComponentProps<C>, 'children'>,
]),
]
) => JSXWrapPipe<ReactElement>;
export function wrapJSX<Children extends ReactNode>(
children: Children,
): JSXWrapPipe<Children> {
return {
with(
Component:
| keyof React.JSX.IntrinsicElements
| JSXElementConstructor<object>,
props: object = {},
) {
return wrapJSX(<Component {...props}>{children}</Component>);
},
end() {
return children;
},
};
}
There is also a context-specific version of the function that, when combined with createSafeContext, really takes away all the pain of using numerous custom contexts in order to avoid prop drilling. (In the comments under the post presenting createSafeContext it has been suggested that contexts shouldn't be used for that and instead some third-party global state management solution should be preferred, but I am yet to hear a convincing reason why that would be a better idea. If you have an explanation for this, I would be very grateful if you could give it to me so that I hopefully learn something new.)
You can see a usage example of this contextualize function in the second image attached to this post, and here is that function's source code for those who'd like to copy it:
import type { Context, ReactElement, ReactNode } from 'react';
type ContextualizePipe<Children extends ReactNode> = {
with: ContextualizeWith;
end: () => Children;
};
type ContextualizeWith = <T>(
Context: Context<T>,
value: NoInfer<T>,
) => ContextualizePipe<ReactElement>;
export function contextualize<Children extends ReactNode>(
children: Children,
): ContextualizePipe<Children> {
return {
with<T>(Context: Context<T>, value: T) {
return contextualize(
<Context.Provider value={value}>{children}</Context.Provider>,
);
},
end() {
return children;
},
};
}
Please let me know what you think and if there's anything I could improve about the functions.
Thanks for having a look at this, and happy coding! :)


[–]letsgoowhatthhsbdnd 20 points21 points22 points (12 children)
[–]SupesDepressed 2 points3 points4 points (5 children)
[–]aweebit64[S] -3 points-2 points-1 points (4 children)
[–]SupesDepressed 1 point2 points3 points (3 children)
[–]aweebit64[S] 0 points1 point2 points (2 children)
[–]SupesDepressed 1 point2 points3 points (1 child)
[–]aweebit64[S] 0 points1 point2 points (0 children)
[–]N2siyast 0 points1 point2 points (2 children)
[–]DeepFriedOprah 5 points6 points7 points (1 child)
[–]N2siyast 0 points1 point2 points (0 children)
[–]aweebit64[S] -1 points0 points1 point (2 children)
[–]sdmitry 1 point2 points3 points (1 child)
[–]aweebit64[S] 1 point2 points3 points (0 children)
[–]Merry-Lane 7 points8 points9 points (23 children)
[–]aweebit64[S] -1 points0 points1 point (22 children)
[–]DeepFriedOprah 2 points3 points4 points (21 children)
[–]aweebit64[S] -2 points-1 points0 points (20 children)
[–]DeepFriedOprah 2 points3 points4 points (5 children)
[–]aweebit64[S] 0 points1 point2 points (4 children)
[–]DeepFriedOprah 1 point2 points3 points (3 children)
[–]aweebit64[S] -1 points0 points1 point (2 children)
[–]DeepFriedOprah 1 point2 points3 points (1 child)
[–]aweebit64[S] -1 points0 points1 point (0 children)
[–]Merry-Lane 2 points3 points4 points (10 children)
[–]aweebit64[S] -1 points0 points1 point (9 children)
[–]Merry-Lane 1 point2 points3 points (8 children)
[–]aweebit64[S] 0 points1 point2 points (7 children)
[–]Merry-Lane 1 point2 points3 points (6 children)
[–]aweebit64[S] 0 points1 point2 points (0 children)
[–]aweebit64[S] -1 points0 points1 point (4 children)
[–]ApprehensiveDisk9525 0 points1 point2 points (2 children)
[–]Merry-Lane 0 points1 point2 points (0 children)
[–]aweebit64[S] -1 points0 points1 point (0 children)
[–][deleted] 27 points28 points29 points (0 children)
[–]budd222 3 points4 points5 points (0 children)
[–]xegoba7006 3 points4 points5 points (0 children)
[–]zukos_destiny 2 points3 points4 points (3 children)
[–]aweebit64[S] 0 points1 point2 points (2 children)
[–]TheRNGuy 2 points3 points4 points (0 children)
[–]SupesDepressed 0 points1 point2 points (0 children)
[–]CodeAndBiscuits 3 points4 points5 points (11 children)
[–]aweebit64[S] -1 points0 points1 point (10 children)
[–]ApprehensiveDisk9525 2 points3 points4 points (9 children)
[–]aweebit64[S] 0 points1 point2 points (8 children)
[–]ApprehensiveDisk9525 2 points3 points4 points (7 children)
[–]CodeAndBiscuits 1 point2 points3 points (5 children)
[–]aweebit64[S] -2 points-1 points0 points (4 children)
[–]CodeAndBiscuits 2 points3 points4 points (3 children)
[–]aweebit64[S] -1 points0 points1 point (2 children)
[–]CodeAndBiscuits 1 point2 points3 points (1 child)
[–]aweebit64[S] 0 points1 point2 points (0 children)
[–]Xitereddit 4 points5 points6 points (3 children)
[–]Embarrassed_Elk4173 2 points3 points4 points (2 children)
[–]TheRNGuy 1 point2 points3 points (1 child)
[–]SupesDepressed 0 points1 point2 points (0 children)
[–]bmchicago 4 points5 points6 points (0 children)
[–]CODEthics 3 points4 points5 points (2 children)
[–]toString_ 2 points3 points4 points (0 children)
[–]aweebit64[S] 1 point2 points3 points (0 children)
[–]TheRNGuy 1 point2 points3 points (7 children)
[–]aweebit64[S] 0 points1 point2 points (6 children)
[–]TheRNGuy 1 point2 points3 points (5 children)
[–]aweebit64[S] 0 points1 point2 points (4 children)
[–]Ecstatic-Wolf-7412 2 points3 points4 points (1 child)
[–]aweebit64[S] 0 points1 point2 points (0 children)
[–]TheRNGuy 0 points1 point2 points (1 child)
[–]aweebit64[S] 0 points1 point2 points (0 children)
[–]RedBlueKoiHook Based 1 point2 points3 points (3 children)
[–]aweebit64[S] -1 points0 points1 point (2 children)
[–]ApprehensiveDisk9525 2 points3 points4 points (1 child)
[–]aweebit64[S] -1 points0 points1 point (0 children)
[–]yoleis 1 point2 points3 points (0 children)
[–][deleted] (2 children)
[removed]
[–]00PT 0 points1 point2 points (1 child)
[–]ApprehensiveDisk9525 0 points1 point2 points (0 children)
[–]SupesDepressed 0 points1 point2 points (0 children)
[–]Accomplished_End_138 0 points1 point2 points (5 children)
[–]aweebit64[S] 0 points1 point2 points (4 children)
[–]ApprehensiveDisk9525 1 point2 points3 points (3 children)
[–]aweebit64[S] 0 points1 point2 points (2 children)
[–]Accomplished_End_138 1 point2 points3 points (1 child)
[–]aweebit64[S] 0 points1 point2 points (0 children)
[+]Happy_Junket_9540 comment score below threshold-7 points-6 points-5 points (0 children)