0.1.0 • Published 2 years ago

@yaireo/react-ref-watcher v0.1.0

Weekly downloads
-
License
MIT
Repository
github
Last release
2 years ago

Use useRef instead of useState by allowing it to be watchable, so a component can choose to act (re-render for example) when a change in the ref is detected.

This is helpful for keeping all the state at a top-level component, and pass it to the sub-components via props or context.

This solves the problem where a child updates a state defined at some top-level parent, which causes the parent to re-render and possibly all the sub-tree as well, which is useless and even harmful for performance in many situations.

Each sub-component can register a listener for changes in a specific ref or any of its current property's properties (assuming current points to a mutated Object/Array).

Install with:

Use from CDN / Download from this repo / NPM

npm i @yaireo/react-ref-watcher -S

What's in this package?

1️⃣ useWatchableRef

ArgumentTypeInfo
initialValueAnySame as the native useRef

Create a ref-like object that listens to any change in the current property and fires all registered callbacks when a change happens to the current property.

Think of this as a regular useRef with the bonus of being watchable. See examples down.

import {useWatchableRef} from '@yaireo/react-ref-watcher'

const Component = () => {
  const myRef = useWatchableRef(true)
}

2️⃣ useWatchableListener

ArgumentTypeInfo
refObjectan Object/Array to listen to
propNameString(optional) specific property name to watch within the ref
watcherfunction(optional) argument, for custom watcher

Listens to refs changes. By default will trigger a re-render in the component which is using this hook if a change in the ref itself or specific property is detected.

In this example, assume ref1 & ref2 were created using useWatchableRef.

import {useWatchableListener} from '@yaireo/react-ref-watcher'

const Component = ({ ref1 }) => {
  const {ref2} = useContext(MyContext) // getting a ref from somewhere up the tree

  useWatchableListener(ref1) // triggers a re-render when ref1 changes (assuming the `ref1.current` is pointing now a new pointer in memory)
  useWatchableListener(ref2.current, 'foo') // triggers a re-render when `foo` property changes in ref2.current (assuming ref2.current is an Object)
}

3️⃣ useWatchableEffect

ArgumentTypeInfo
callbackFunctionfires when a ref change detetced
dependenciesArrayarray of watchable refs

Listen to changes in a ref without triggering a re-render

import {useWatchableEffect, useWatchableListener} from '@yaireo/react-ref-watcher'

const Component = ({ ref1, ref2 }) => {
  // when `ref1` changes, run the callback
  useWatchableEffect(() => {
    ref2.current = ref1 === 'foo';
  }, [ref1])

  // ref2 is dependend on ref1. Only when ref2 changes the component should re-render
  useWatchableListener(ref2)
}

4️⃣ propWatcher

Unlike the other hooks, this is a utility function which does the actual watching. It adds an enumerable __WATCHERS property (will host callback listeners when changes detected) on top of the argument (expected to be an Object) and then returns a new proxy which encapsulates the argument.

Every time a propery is modified or deleted (in your code) the proxy trap will fire and all callback functions defined in the __WATCHERS property will fire.

Any Object may be wrapped with propWatcher to become "watchable" (not only React refs). Example of most basic usage:

import {propWatcher} from '@yaireo/react-ref-watcher'

const watchableRef = propWatcher({ current: true })