A compilation of everything everyone is doing with Async React, for easy demoing and experimentation.
WARNING: THIS IS NOT TO BE USED FOR PRODUCTION
This library helps people experiment with Async React as explored by the community.
Non Suspense Demo Clones
npm install --save async-react-future
Note: all of the below must be used inside ReactDOM's coming <AsyncMode>
.
Dan Movie Demo Components
Placeholder
Placeholder component from Dan's demo
This is a simple wrapper for Timeout; frankly if you know Timeout well you don't have to use this.
You want one of these above any suspending you're going to do.
const {
delayMs = 1, // note that react has hardcorded expirations at 1s and 5s
fallback = 'Loading', // any jsx here will do
children // required
} = props;
import { future: { Placeholder } } from 'async-react-future';
// later...
<Placeholder delayMs={1000} fallback={<div className="Spinner" />}>
{/* stuff with suspenders in here */}
</Placeholder>
Component
new React.Component from Dan's demo
Just adds deferSetState to React.Component, which passes things through ReactDom.deferredUpdates before setting component state
N/A
import { future: { Component } } from 'async-react-future';
class App extends Component {
state = { showDetail: false };
handleClick = id => {
this.deferSetState({ showDetail: true });
};
render() {
// use this.handleClick somewhere
}
}
Img
Img component from Dan's demo
Suspends image fetching. pretty much.
const {
src, // required
alt = '', // probably required
...rest
} = props;
import { future: { Img } } from 'async-react-future';
// later
<Img src={src} alt="poster" />
Misc components
Never
Never component from Suspense test
Throws a promise that resolves after some arbitrarily large number of seconds. The idea is that this component will never resolve. It's always wrapped by a Timeout.
N/A
import { future: { Never } } from 'async-react-future';
function Delay({ms}) {
return (
<Timeout ms={ms}>
{didTimeout => {
if (didTimeout) {
// Once ms has elapsed, render null. This allows the rest of the
// tree to resume rendering.
return null;
}
return <Never />;
}}
</Timeout>
);
}
Delay
Delay component from Suspense test
Delay a render of peer components by ms
milliseconds. Can be used to debounce, for example. Once ms has elapsed, render null. This allows the rest of the tree to resume rendering.
N/A
import React, {Fragment} from 'react';
import { future: { Delay } } from 'async-react-future';
function DebouncedText({text, ms}) {
return (
<Fragment>
<Delay ms={ms} />
<Text text={text} /> {/* defined elsewhere */}
</Fragment>
);
}
LowPriority
LowPriority component from Peggy's ReactEurope demo
Defers (makes low priority) prop changes to its children through manipulating a value
prop on a stateKey
.
from https://github.com/peggyrayzis/react-europe-apollo
const {
stateKey, // required, string
value, // required, any
children // function as a child, gets the deferred props passed to LowPriority
} = this.props;
import { future: { LowPriority } } from 'async-react-future';
import React, {Timeout} from 'react'
// later
<LowPriority
stateKey="selectedDog"
value={this.state.selectedDog}> {/* not deferred */}
{selectedDog => ( // deferred
<Timeout ms={2000}>
{expired =>
expired && selectedDog ? (
<Loading /> {/* defined elsewhere */}
) : (
<Photo breed={selectedDog} /> {/* defined elsewhere */}
)
}
</Timeout>
)}
</LowPriority>
Raw Data
Raw movie data to make demo clones
- moviesOverview (array of movie objects)
- movieDetailsJSON (an object map of movie id: movie detail object)
- movieReviewsJSON (an object map of movie id: movie review object)
import {
mockapi: { moviesOverview },
movieDemo: { MovieListPage}
} from 'async-react-future';
// later
<MovieListPage
onMovieClick={handleMovieClick} {/* defined elsewhere */}
loadingId={currentId} {/* defined elsewhere */}
moviesOverview={moviesOverview}
/>
Fetch Data
Async wrappers with delays for the raw data
- fetchMovieList
- fetchMovieDetails
- fetchMovieReviews
import {
future: { createFetcher },
mockapi: { fetchMofetchMovieReviewsvieList },
movieDemo: { MovieListPage}
} from 'async-react-future';
const movieReviewsFetcher = createFetcher(fetchMovieReviews);
function MovieReviews({ movieId }) {
const reviews = movieReviewsFetcher.read(movieId);
return <div className="MovieReviews">{reviews.map(review => <div key={review}>{review}</div>)}</div>;
}
Utilities
Just a delay
function for now
export const fetchMovieDetails = async (id, delayMS = 100) => {
await delay(delayMS);
return movieDetailsJSON[id];
};
Styled components that help to rapidly recreate demo clones and minimize code people have to dig through.
MovieListPage
A MovieListPage
A MovieListPage
import {
mockapi: { moviesOverview },
movieDemo: { MovieListPage}
} from 'async-react-future';
// later
<MovieListPage
onMovieClick={handleMovieClick} {/* defined elsewhere */}
loadingId={currentId} {/* defined elsewhere */}
moviesOverview={moviesOverview}
/>
The rest of this documentation is yet to be completed.
Spinner
A simple Spinner
A simple css spinner that always spins, pass size={'large'}
for 2x size
import {
future: { Placeholder }
movieDemo: { Spinner }
} from 'async-react-future';
// later...
<Placeholder delayMs={1000} fallback={<Spinner />}>
{/* stuff with suspenders in here */}
</Placeholder>
I have studied a lot of people's code and you are likely to see shades of your code pop up here and there. I don't claim any rights at all to any of this. I'll try to attribute as many people as possible but apologies in advance if I forgot to include you.
- https://github.com/BenoitZugmeyer/react-suspense-demo for much of the
./future
API - https://medium.com/@pete_gleeson/creating-suspense-in-react-16-2-dcf4cb1a683f for
Loading
- https://github.com/pomber/hitchcock/blob/master/src/cache.js for cache
Library was bootstrapped with: https://github.com/transitive-bullshit/create-react-library
MIT © sw-yx