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

usestable

v0.1.25

Published

A React hook to create stable component/object

Downloads

59

Readme

useStable

A React hook to create stable component/object

Installation

with NPM

npm i usestable --save

with YARN

yarn add usestable

Motivation

Inspired by useEvent RFC

Recipes

Stable identity callback

with useEvent

import { useEvent } from "react";

function Chat() {
  const [text, setText] = useState("");

  const onClick = useEvent(() => {
    sendMessage(text);
  });

  return <SendButton onClick={onClick} />;
}

with useStable

import { useStable } from "react";

function Chat() {
  const [text, setText] = useState("");
  const stable = useStable({
    onClick: () => {
      sendMessage(text);
    },
  });

  return <SendButton onClick={stable.onClick} />;
}

Stable component

For above examples, you must wrap your SendButton with memo(). Need to useEvent every time and easy to forget. usestable provide stable() HOC to create a stable component on the fly

import { stable } from "usestable";

const SendButton = stable((props) => {
  // implementation
});

// you also wrap 3rd-party components
import { Button } from "antd";

// even with specified props only. by default, all props will be stable
const SendButton = stable(Button, { props: ["onClick"] });

There you go, no need to wrap any event callbacks. You also free with inline callbacks

function Chat({ rooms }) {
  const [text, setText] = useState("");

  return rooms.map((room) => (
    <SendButton
      // if you wrap SendButton with stable(), you dont not worry this
      onClick={
        () => sendMessage(room, text)
        // 🙁 Can't wrap it with useEvent
      }
    />
  ));
}

Geting fresh values in callbacks

Sometimes, useEvent fails with async callback

with useEvent

const contextVariable = useContext(SomeContext);
const callback = useEvent(async () => {
  // the contextVariable is fresh now
  console.log(contextVariable);
  await callAsyncMethod();
  // but it is outdated now
  console.log(contextVariable);
});

You must use more useEvent hook to handle above case

const contextVariable = useContext(SomeContext);
const onDone = useEvent(() => {
  // do something with contextVariable
});
const callback = useEvent(async () => {
  // the contextVariable is fresh now
  console.log(contextVariable);
  await callAsyncMethod();
  onDone();
});

with useStable #1

import { useStable } from "usestable";

const contextVariable = useContext(SomeContext);
// create stable object to hold contextVariable
const stable = useStable({ contextVariable });
const callback = useCallback(async () => {
  // the contextVariable is fresh now
  console.log(stable.contextVariable);
  await callAsyncMethod();
  // and it is still fresh now and after. Easy ?
  console.log(stable.contextVariable);
}, [stable]);

with useStable #2

import { useStable } from "usestable";

const contextVariable = useContext(SomeContext);
// create stable object to hold contextVariable
const { callback } = useStable({
  // add contexture variables
  contextVariable,
  // define async callback
  async callback() {
    // using this object to access stable props
    // the contextVariable is fresh now
    console.log(this.contextVariable);
    await callAsyncMethod();
    // and it is still fresh now and after. Easy ?
    console.log(this.contextVariable);
  },
});

Using stable object with other React hooks

You can use stable object with any React's hooks

const stable = useStable({
  some,
  stable,
  variables,
  here,
  dateValue, // useStable will not update date values if its timestamp does not change
  stableCallback() {},
});

const flexibleCallback = useCallback(() => {
  console.log(unstableVar);
  console.log(stable.variables);
}, [stable, unstableVar /* add dependencies to control callback re-create */]);

useEffect(() => {
  socket.on("connected", () => {
    console.log(stable.some);
    console.log(stable.variables);
  });
}, [stable /* add more dependencies ad you need */]);

Conditional callbacks

Sometimes React memo and useEvent fail with conditional callbacks

function Chat({ onOdd, onEven }) {
  const [text, setText] = useState("");

  return <SendButton onClick={text.length % 2 ? onEven : onOdd} />;
}

You must add more useEvent hook to handle conditional callbacks

function Chat({ onOdd, onEven }) {
  const [text, setText] = useState("");
  const onClick = useEvent(() => (text.length % 2 ? onEven() : onOdd()));

  return <SendButton onClick={onClick} />;
}

If SendButton already wrapped by stable() HOC, everything done without any effort

API reference

https://linq2js.github.io/usestable/