# shared-state-react

> A way to avoid drilling down props

Latest version **0.1.2** (published 2020-05-30) · MIT license · 0 weekly downloads

## Install

```sh
npm install shared-state-react
pnpm add shared-state-react
yarn add shared-state-react
bun add shared-state-react
```

## Health

**Score 15/100 (F)** — status: abandoned.

Positive: no vulnerabilities.

Warnings: low downloads; no types; no esm support; pre 1.0.

Negative: abandoned; low maintenance score.

## Facts

| | |
|---|---|
| Version | 0.1.2 |
| Published | 2020-05-30 |
| First published | 2020-05-25 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | none |
| Module format | CommonJS |
| Dependencies | 0 |
| Unpacked size | 22.5 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 0 |
| Author | Chandrakumar |
| Maintainers | dreamerchandra |
| Keywords | react, avoidDrillingDownProps, avoidDeepNestedProps |

## Links

- npm: https://www.npmjs.com/package/shared-state-react
- Repository: https://github.com/dreamerchandra/shared-state
- Homepage: https://github.com/dreamerchandra/shared-state#readme
- Issues: https://github.com/dreamerchandra/shared-state/issues
- npm.io page: https://npm.io/package/shared-state-react

## Alternatives

- [mobx-react](https://npm.io/package/mobx-react.md) — 2.8M weekly downloads
- [rc-tree](https://npm.io/package/rc-tree.md) — 2.6M weekly downloads
- [@react-oauth/google](https://npm.io/package/@react-oauth/google.md) — 1.3M weekly downloads
- [@wagmi/connectors](https://npm.io/package/@wagmi/connectors.md) — 877.0K weekly downloads
- [vee-validate](https://npm.io/package/vee-validate.md) — 836.4K weekly downloads

## Recent versions

- 0.1.2 (latest) — 2020-05-30
- 0.1.1 — 2020-05-25
- 0.1.0 — 2020-05-25

## 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 
 - flux based architecture such as [redux](https://redux.js.org/), [mobx](https://mobx.js.org/README.html)
 - sharing the react state with context
 - [Using composition to avoid props drilling](https://www.youtube.com/watch?v=3XaXKiXtNjw&feature=emb_title)

## 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)
```

---
_Source: https://npm.io/package/shared-state-react · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
