Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/danieldelcore/react-stable-ref

A set of utilities for testing against unstable references in React 🤷‍♂️
https://github.com/danieldelcore/react-stable-ref

hooks react reactjs testing testing-tools unstable-references

Last synced: 13 days ago
JSON representation

A set of utilities for testing against unstable references in React 🤷‍♂️

Awesome Lists containing this project

README

        


Test stable references

# react-stable-ref 🤷‍♂️

[![min](https://img.shields.io/bundlephobia/min/react-stable-ref.svg)](https://www.npmjs.com/package/react-stable-ref)
[![npm](https://img.shields.io/npm/v/react-stable-ref.svg)](https://www.npmjs.com/package/react-stable-ref)
[![Downloads per month](https://img.shields.io/npm/dm/react-stable-ref.svg)](https://www.npmjs.com/package/react-stable-ref)

Your stable reference utility library with everything you need to test, visualize and protect against the dreaded unintentional rerender 😱

[Try it here](https://danieldelcore.github.io/react-stable-ref/)

## Get started 🏗

**Installation**

`npm install --save react-stable-ref` or `yarn add react-stable-ref`

## Example

```jsx
const UnstableButton: FC = ({ onClick, children }) => {
// Unstable reference (unstableArray is reassigned on every render)
const unstableArray = ['1', '2', '3'];
const stableValue = 'Im stable because im a string';

useStableRefTester(); // Triggers re-renders every second
useWhichDepChanged({ unstableArray, stableValue });
/**
* Will output the following to the console (or onChange if you pass it in)
*
* > [useWhichDepChanged]: { unstableArray: { from: [1, 2, 3]; to: [1, 2, 3]}}
*/

return (

{children}

);
};
```

## Motivation 🧠

It's not always obvious when unstable references are passed into hooks such as `useEffect`. This can cause unnecessary rerenders, which when left unchecked can decrease the performance of your app, cause jank and ultimately degrade your user's experience 😭.

Thankfully the React team have already thought about this and provided [lint rules to help](https://www.npmjs.com/package/eslint-plugin-react-hooks) 🥰. But what if you're passing objects and arrays into dependency arrays which are not 'deeply' compared? How can you know for sure?

`react-stable-ref` fills that gap and provides an assortment of utilities to help test, visualize and protect against the dreaded re-render 😱.

## API 🤖

### `useStableRefTester()`

A **development only** hook, which increments state over a predefined interval, triggering rerenders in your component.

**Arguments:**

- timeout: `Number` Timeout between rerenders

**Returns:**

count: `Number`

**Example:**

```jsx
const UnstableButton = ({ children }) => {
const myArray = ['1', '2', '3'];

useStableRefTester();

useEffect(() => {
console.warn('I should not be called on every render');
}, [myArray]);

return {children};
};
```

### `useWhichDepChanged()`

A **development only** hook which emits (via console) which prop triggered an update. Useful when you are unsure which property changed in a `useEffect` dependency array.

_Inspired by_: [useWhyDidYouUpdate](https://usehooks.com/useWhyDidYouUpdate/)

**Arguments:**

- dependencies: `Object` A dependency object which mirrors the dependency array of the hook you are trying to test
- onChange(changedDeps): `(changedDeps: Obj) => void` A callback which is fired when a dependency is changed.

**Returns:**

`void`

**Example:**

```jsx
const UnstableButton = ({ children }) => {
const myArray = ['1', '2', '3'];

useWhichDepChanged({ myArray, children }, onChange(changedDeps) => {
console.log('UnstableButton: ', changedDeps); // UnstableButton: myArray
});

return {children};
};
```

### `useRenderCount()`

A hook which returns how many times it has been rendered.

**Arguments:**

- initialCount: `Number` Initial counter value

**Returns:**

- count: `Number` Current counter value

**Example:**

```jsx
const RenderCounter = () => {
const count = useRenderCount();

return {count};
};
```

### ``

A visual component that keeps track of the number of renders that have occurred.


Render count component

**Props:**

- initialCount: `Number` Initial counter value
- count: `Number` Provide a count for a controlled API

### `useDeeplyComparedEffect()`

_Coming soon..._

A react hook for deeply comparing objects and arrays passed into its dependency array.

### `useCustomComparedEffect()`

_Coming soon..._

A react hook to allow you to provide custom methods used to comparing dependencies and trigger an effect.

## Thanks 😍

Huge thank you to [Pablo Stanley](https://twitter.com/pablostanley) and contributors of [Open Peeps](https://www.openpeeps.com/?ref=react-stable-ref) for the logo.

## Resources

- [Introducing Hooks](https://reactjs.org/docs/hooks-intro.html)
- [Making Sense of React Hooks](https://medium.com/@dan_abramov/making-sense-of-react-hooks-fdbde8803889)
- [When to useMemo and useCallback](https://kentcdodds.com/blog/usememo-and-usecallback/)