npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

compose-hooks

v1.0.5

Published

Use a HOC in order to separate hooks & logic from the presentational component.

Downloads

324

Readme

🪢 compose-hooks 🪢

Make your React Components purely presentational, and simply bind the props for them in a declarative manner.

Why?

When I tried some different "compose hooks" libraries on npm, for each one I missed some feature or configurability. None of them supported the full control I felt required for all situations, so this version enables just a few key control features.

  • 0 dependencies, but of course React is a peer dependecy.

composeHooks

Overview

This HOC (Higher Order Component) wraps a component in order to attach hooks, props & behaviors.

It enables the separation of presentation from logic & behavior, like this:

// MyComp.jsx

const MyCompPresenter = ({ ...props }) => (
  <View>
    <Text>
      {`Here is the pure JSX content,`}
      {`which means these type of pure component functions Never have bodies, only direct returns of JSX.`}
      {`This is because all logic, hooks etc is bound via composeHooks and enter here as props.`}
      {`A good pattern is for these presenter components to always end in "...Presenter".`}
    </Text>
  </View>
);

export const MyComp = composeHooks({
  // Hooks and prop creations (See below)
})(MyCompPresenter);

Syntax & behavior

First and foremost:

  • Each value will be executed as a function at render.

Then, the composeHooks basically have 4 behaviors for the key-values in the object given to it:

  • Props from the parent will by default override the props from composeHooks.
  • A prefix > in the key string will inject all props up until that point into the value function.
  • A postfix ! in the key string will make this prop override that prop possibly coming from the parent.
  • The result of a value function call will be spread into props if the key string begins with use followed by a capital letter, as in e.g. useValue. (Otherwise the result will directly be assigned to the prop.)

Examples

Let's see some examples of what the key-values can be and look like.

export const MyComp = composeHooks({
  /* Simplest use. The hook returns an object that will be spread into props. */
  useExpanded,
  /* Hook returns something/anything that we want to assign to `theme` prop. */
  theme: useTheme,
  /* We can use a simple function to return a constant value, and... */
  noUppercase: () => true,
  /* ...with the `!` syntax overwrite the possible incoming prop with the same name. */
  'icon!': () => 'arrow-right',
  /* Same as above with an object put into `labelStyle` (and overriding parent prop). */
  'labelStyle!': () => ({ flex: 1 }),
  /* Putting a ">" first will inject all previous props into the function. Hence, we can use `theme` here. */
  '>color': ({ theme }) => theme.colors.onPrimary,
  /* Combine `>` & `!` to use incomming props and then overwrite.
  (This pattern is especially useful for `style`.) */
  '>style!': ({ theme, style }) => ({
    backgroundColor: theme.colors.onSurfaceVariant,
    ...style,
  }),
  /* If our custom hook `useCustomHook` needs some props, but we want the returned object to
  be spread into all final props, we can give it a dummy name that follows the naming convention
  of React Hooks. */
  '>useSpread': useCustomHook,
  /* Using e.g. ramda can be a nice point-free style way of selecting/using something from a hook call. */
  t: R.pipe(useTranslation, R.head),
})(MyCompPresenter);

A possible output (props for the Presenter) from the above composed hooks etc could be:

const MyCompPresenter = ({
  expanded,
  toggleExpanded,
  theme,
  noUppercase,
  icon,
  labelStyle,
  color,
  style,
  someValueFromCustomHook,
  anotherValueFromCustomHook,
  t,
}) => (
  // ...
);

Happy coding!

Licence

MIT