Created
January 16, 2023 02:38
-
-
Save ARHEIO/eddcc6a713dbd73f275dc90023eb313b to your computer and use it in GitHub Desktop.
Render Props vs React Context
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
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> | |
); | |
} |
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
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