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

shared-state-react

v0.1.2

Published

A way to avoid drilling down props

Downloads

1

Readme

Problem

Flags such as isOpened, toBeShown, wasXChanged, isXValid, isDataProperToFetch and whatever you name it plays a major role in development process and there are times where I hit a point to nest these flags 3 to 4 component throughout the tree sad truth is all connected components re-renders.

Existing Solutions

Resolving nested props requires either of

Problems

flux based architecture

one linear: you are affecting the whole store

IMHO, one can put anything in store but take a step back and question how many places you need to refactors before shipping a single state to store especially in hooks. To name a few

  • look for dependency
  • create reducer(s)
  • updating mapStateToProps
  • updating corresponding parts of the component
  • rewriting hooks to call a function in mapDispatchToProps

Sharing the react state with context

Works fine expect it re-render consumers for unnecessary state updates

const AppContext = createContext();
Parent = () => {
  const [flags, setFlags] = useState({a: 1, b: 2});
  const [timeOfMount, setToM] = useState();
  useEffect(() => setToM(new Date()), [])
  return (
    <>
      // renders values are only for single `setFlags` and does not include mounting phase
      <p>{timeOfMount}</p> // renders onces
      <AppContext.Provider value=flags>
        <Child> // renders twice and also for `setToM`
      </AppContext.Provider>
    </>
  )
}

Besides it re-renders for unnecessary state; update a single change(such as key a) in context value triggers re-renders in all the child component which also a wasted render

Using composition to avoid props drilling

Yea it works again refactoring matters and the same problem with context follows

My Idea

Create a observer whenever you want to share your state and listen to the changes in the consumer.

Example

import { useToCreateSharedProps, useToConsumeSharedProps } from 'shared-state';
const Parent = () => {
    const [counter1, setCounter1] = useState(1);
    const [counter2, setCounter2] = useState(1);

      useToCreateSharedProps('Parent', {
        counter1, counter2,
      });
      return (
        <>
          <MemoCounter id=1 /> // you can go with dynamic ids as well
          <MemoCounter id=2 />
        </>
      )
}

const Counter = ({ id }) => {
  let counter = useToConsumeSharedProps('Parent', `counter${id}`);
  return(<p>Counter1: {counter1}<p/>)
}
const MemoCounter = React.memo(Counter); // since counter is not a part of props we don't need this component to re-render

How it works

useToCreateSharedProps create a object with an ability to track changed values and update the corresponding observer which are added with useToConsumeSharedProps. This library uses === to check if something has changed. So read bonus tip for custom part of useToConsumeSharedProps

For eg: useToCreateSharedProps('key', {counter1, counter2}); create a sharedStateManager object. useToConsumeSharedProps('key', 'counter1'); create a listener for counter1. First Parameter key lets you to use same object names counter1 for different parts of the react tree (basically to avoid conflicts of using same flag name such as isOpened and all those). But since you are sharing the your state you have to be descriptive with what was isOpened referring to, or you could go wild with useToCreateSharedProps('TopHeaderDropBox', {isOpened}); which ever approach works fine for you.

Bonus Tip

Third arg of useToConsumeSharedProps accepts a callback. If it returns true the consumer will be updated.

const user = {
  id1: {
    name: 'harry potter',
    canCastSpellOutsideSchool: false
  }
  id2: {
    name: 'George Weasley',
    canCastSpellOutsideSchool: true
  }
}
useToCreateSharedProps('Magicians', {users}); // in the sharing part
const updateOnlyIfUserAdds = (oldVal, newVal) => Object.keys(oldVal).length !== Object.keys(newVal).length
const userList = useToConsumeSharedProps('Magicians', 'users', updateOnlyIfUserAdds)