GithubHelp home page GithubHelp logo

pomber / hitchcock Goto Github PK

View Code? Open in Web Editor NEW
168.0 7.0 5.0 2.51 MB

The Master of Suspense 🍿

License: MIT License

JavaScript 100.00%
react suspense cache loader component debug debugger async dev-tools concurrent

hitchcock's Introduction

β€œThere is no terror in the bang, only in the anticipation of it.”

β€” Alfred Hitchcock

Hitchcock npm version

Hitchcock is a debugging tool for React Suspense. It wraps your calls to React.lazy(), provides a simple cache (based on react-cache) and let you pause, delay or invalidate your promises.

🚨 EXPERIMENTAL 🚨

Use this only for experimenting with the new React Concurrent Mode. Hitchcock is inefficient and unstable. Also, I have no idea what I'm doing.

Demos

The code is in the examples folder.

Usage

Try it on CodeSandbox

Add the dependency:

$ yarn add hitchcock

Director

Import the Director component and add it somewhere in your app:

import { Director } from "hitchcock";

function YourApp() {
  return (
    <Director>
      <YourStuff />
    </Director>
  );
}

Lazy

Instead of using React.lazy import lazy from hitchcock:

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

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 (
    <>
      <h1>{beer.name}</h1>
      <p>{beer.description}</p>
    </>
  );
}

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. 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:

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 (
    <Director>
      Beer # <input type="number" value={beerId} onChange={handleChange} />
      <Suspense fallback={<div>{`Loading beer #${beerId}...`}</div>}>
        {showBeer && <Beer beerId={deferredBeerId} />}
      </Suspense>
    </Director>
  );
}

function Beer({ beerId }) {
  const beer = BeerResource.read(beerId);
  return (
    <>
      <h1>{beer.name}</h1>
      <p>{beer.description}</p>
    </>
  );
}

const container = document.getElementById("root");
ReactDOM.createRoot(container).render(<App />);

Contributing

$ git clone [email protected]:pomber/hitchcock.git
$ cd hitchcock
$ npx lerna bootstrap

Run the examples:

$ yarn start:example movies
$ yarn start:example suspensify

Publish new version:

$ yarn build:packages
$ npx lerna publish

License

Released under MIT license.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.