Description
Unfortunately RFC was rejected: reactjs/rfcs#197
This means usage of the hook API will continue to be rather painful when branching/mapping is involved.
Potential pivot: a component API!
// Naming tbd
<UseStyles with={<div {...anyDivProps} />} display="flex">
children here
</UseStyles>
Internally, implemented as:
const UseStyles = ({ with, children, ...styles }) => {
return React.cloneElement(with, {
className: useStyles(styles, Object.entries(styles).flat()),
null,
children
})
}
Nice thing here is dependency analysis becomes automatic, unfortunately doesn't look very performant... Still worth benchmarking though.
Alternatively, a more direct translation:
// Naming tbd
<UseStyles with={div} styles={{ display: "flex" }} dependencies={[]} {...anyDivProps} >
children here
</UseStyles>
const UseStyles = ({ with, children, styles, dependencies, ...props }) => {
return React.createElement(with, {
className: useStyles(styles, dependencies),
props,
children,
})
}
Lastly, it might be worth trying generating the dependency list automatically from styles using the flattened entries approach above, directly inside the hook implementation (breaking change), and adopt if perf doesn't suffer significantly. Not having to supply a dependency array would improve ergonomics by a boatload. Alternatively, we can make this behavior default but allow users to optimize by supplying an optional dependency list.
https://github.com/lewisl9029/use-styles/blob/master/src/useStyles.js#L172
to
const cacheEntries = React.useMemo(() => toCacheEntries(styles), Object.entries(styles).flat())
One more idea: Let users specify if they're passing in memoized styles to begin with.
const cacheEntries = React.useMemo(() => toCacheEntries(styles), props.memoized ? styles : Object.entries(styles).flat())
Can also split into dynamic vs static styles props.