Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/pomber/hitchcock
The Master of Suspense πΏ
https://github.com/pomber/hitchcock
async cache component concurrent debug debugger dev-tools lazy loader react react-cache suspense
Last synced: 7 days ago
JSON representation
The Master of Suspense πΏ
- Host: GitHub
- URL: https://github.com/pomber/hitchcock
- Owner: pomber
- License: mit
- Created: 2018-03-14T18:18:31.000Z (almost 7 years ago)
- Default Branch: master
- Last Pushed: 2019-10-27T18:43:53.000Z (about 5 years ago)
- Last Synced: 2024-04-25T23:20:56.949Z (8 months ago)
- Topics: async, cache, component, concurrent, debug, debugger, dev-tools, lazy, loader, react, react-cache, suspense
- Language: JavaScript
- Homepage:
- Size: 2.45 MB
- Stars: 168
- Watchers: 7
- Forks: 5
- Open Issues: 1
-
Metadata Files:
- Readme: readme.md
- License: license
Awesome Lists containing this project
README
> βThere is no terror in the bang, only in the anticipation of it.β
>
> β Alfred Hitchcock# Hitchcock [![npm version](https://img.shields.io/npm/v/hitchcock.svg?style=flat)](https://www.npmjs.com/package/hitchcock)
**Hitchcock is a debugging tool for React Suspense.** It wraps your calls to `React.lazy()`, provides a simple cache ([based on react-cache](https://github.com/facebook/react/tree/master/packages/react-cache)) and let you pause, delay or invalidate your promises.
### π¨ EXPERIMENTAL π¨
Use this only for experimenting with [the new React Concurrent Mode](https://reactjs.org/docs/concurrent-mode-intro.html). Hitchcock is inefficient and unstable. Also, I have no idea what I'm doing.
## Demos
- [**Movies**](https://hitchcock-movies.netlify.com):
A clone of [@karl clone](https://github.com/karl/react-async-io-testbed) of [@dan_abramov demo](https://www.youtube.com/watch?v=6g3g0Q_XVb4)
- [**Suspensify**](https://hitchcock-suspensify.netlify.com):
A clone of the [suspense demo](https://github.com/jaredpalmer/react-conf-2018) from [Jared Palmer](https://twitter.com/jaredpalmer)'s [React Conf talk](https://www.youtube.com/watch?v=SCQgE4mTnjU&feature=youtu.be).The code is in the [examples folder](https://github.com/pomber/hitchcock/tree/master/examples).
## Usage
> Try it on [CodeSandbox](https://codesandbox.io/s/ovqlz507pz)
Add the dependency:
```bash
$ yarn add hitchcock
```### Director
Import the `Director` component and add it somewhere in your app:
```jsx
import { Director } from "hitchcock";function YourApp() {
return (
);
}
```### Lazy
Instead of using `React.lazy` import `lazy` from hitchcock:
```jsx
import { lazy } from "hitchcock";const HomePage = lazy(() => import("./components/HomePage"));
// Hitchcock's lazy accepts a second parameter with the name of the component:
const ArtistPage = lazy(() => import("./components/ArtistPage"), "ArtistPage");
// it's optional, but recommended, it isn't always easy to guess the name from the import
```### createResource
```jsx
import { createResource } from "hitchcock";const BeerResource = createResource(
id =>
fetch(`https://api.punkapi.com/v2/beers/${id}`)
.then(r => r.json())
.then(d => d[0]),
id => `beer-${id}`
);function Beer({ beerId }) {
const beer = BeerResource.read(beerId);
return (
<>
{beer.name}
{beer.description}
>
);
}
````createResource` has two parameters. The first one is a function that returns a promise. The second one is a function that returns an id, that id is used as the key in the cache and also is used as the name of the resource in the debugger.
It returns a `resource` with a `read` method that will suspend a component until the resource is ready (when the promise resolves).
### Waterfalls
[React docs warn about using Suspense as a way to start fetching data when a component renders](https://reactjs.org/docs/concurrent-mode-suspense.html#for-library-authors). The recommended approach is to start fetching before rendering, for example, in an event handler. Hitchcock doesn't solve this problem, but it provides a `preload` method if you want to try:
```jsx
import React, { Suspense } from "react";
import ReactDOM from "react-dom";
import { createResource, Director } from "hitchcock";const BeerResource = createResource(
id =>
fetch(`https://api.punkapi.com/v2/beers/${id}`)
.then(r => r.json())
.then(d => d[0]),
id => `beer-${id}`
);function App() {
const [beerId, setBeerId] = React.useState(0);
const deferredBeerId = React.useDeferredValue(beerId, { timeoutMs: 1000 });const showBeer = deferredBeerId > 0;
const handleChange = e => {
const newBeerId = +e.target.value;
BeerResource.preload(newBeerId);
setBeerId(newBeerId);
};return (
Beer #
{`Loading beer #${beerId}...`}}>
{showBeer && }
);
}function Beer({ beerId }) {
const beer = BeerResource.read(beerId);
return (
<>
{beer.name}
{beer.description}
>
);
}const container = document.getElementById("root");
ReactDOM.createRoot(container).render();
```## Contributing
```bash
$ git clone [email protected]:pomber/hitchcock.git
$ cd hitchcock
$ npx lerna bootstrap
```Run the examples:
```bash
$ yarn start:example movies
$ yarn start:example suspensify
```Publish new version:
```bash
$ yarn build:packages
$ npx lerna publish
```## License
Released under MIT license.