Skip to content

Instantly share code, notes, and snippets.

@ARHEIO
Created January 16, 2023 02:38
Show Gist options
  • Save ARHEIO/eddcc6a713dbd73f275dc90023eb313b to your computer and use it in GitHub Desktop.
Save ARHEIO/eddcc6a713dbd73f275dc90023eb313b to your computer and use it in GitHub Desktop.
Render Props vs React Context
import React, { createContext, PropsWithChildren, useContext } from 'react';
type OnMouseClickEvent = React.MouseEvent<HTMLButtonElement, MouseEvent>;
const DemoContext = createContext<{
onClick: (ev: OnMouseClickEvent) => void;
}>({
onClick: () => undefined,
});
/**
* Provides root context that all the other subcomponents can use.
*/
export function DemoWrapper({ children }: PropsWithChildren): JSX.Element {
const onClick = (ev: OnMouseClickEvent): void => {
console.log('%c⧭', 'color: #bfffc8', ev);
};
return (
<DemoContext.Provider
value={{
onClick,
}}
>
{children}
</DemoContext.Provider>
);
}
/**
* Interacts with context to do a thing.
*/
export function DemoButton({ children, ...props }: Omit<JSX.IntrinsicElements['button'], 'onClick'>): JSX.Element {
const { onClick } = useContext(DemoContext);
return (
<button onClick={onClick} {...props}>
{children}
</button>
);
}
/**
* The library's implementation is completely hidden from the consumer.
* But the consumer has to use the provided elements
*/
function Usage(): JSX.Element {
return (
<DemoWrapper>
<div>
<DemoButton style={{ height: '100px', width: '100%' }}>asdfasdf</DemoButton>
</div>
</DemoWrapper>
);
}
import React from 'react';
const isFunction = (obj: unknown): obj is Function => typeof obj === 'function';
type OnMouseClickEvent = React.MouseEvent<HTMLButtonElement, MouseEvent>;
/**
* Props for the parent component.
* Anything provided in `props` can be used by the consumer
*/
interface Props {
children: (props: { onClick: (ev: OnMouseClickEvent) => void }) => JSX.Element;
}
export function RenderPropsDemonstration({ children }: Props): JSX.Element {
const onClick = (ev: OnMouseClickEvent): void => {
console.log('%c⧭', 'color: #bfffc8', ev);
};
if (isFunction(children)) {
return children({ onClick });
}
return <></>;
}
/**
* The library defines the `onClick` functionality.
* But the consumer gets to choose where to apply it.
*/
function Usage(): JSX.Element {
return (
<RenderPropsDemonstration>
{({ onClick }) => (
<div>
<button onClick={onClick} style={{ height: '100px', width: '100%' }}>
asdfasdf
</button>
</div>
)}
</RenderPropsDemonstration>
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment