import React, { useState } from 'react';
import axios from 'axios';
import { Alert, Box, Button, Group, Heading, Image, Input, Set, Spinner } from 'fannypack';
import { storiesOf } from '@storybook/react';
import { cache, useCache, useGetStates, useLoads, useDeferredLoads } from '../index';
import * as api from './api';
storiesOf('useLoads', module)
.add('basic', () => {
function Component() {
const getRandomDog = React.useCallback(() => axios.get('https://dog.ceo/api/breeds/image/random'), []);
const randomDogRecord = useLoads('basic', getRandomDog);
return (
{randomDogRecord.isPending && }
{randomDogRecord.isResolved && (
)}
{randomDogRecord.isRejected && {randomDogRecord.error.message}}
);
}
return ;
})
.add('basic (deferred)', () => {
function Component() {
const getRandomDog = React.useCallback(() => axios.get('https://dog.ceo/api/breeds/image/random'), []);
const randomDogRecord = useDeferredLoads('basic', getRandomDog);
return (
{randomDogRecord.isIdle && }
{randomDogRecord.isPending && }
{randomDogRecord.isResolved && (
)}
{randomDogRecord.isRejected && {randomDogRecord.error.message}}
);
}
return ;
})
.add('with function variables', () => {
function Component() {
const [breed, setBreed] = React.useState('beagle');
const getRandomDogByBreed = React.useCallback(
breed => axios.get(`https://dog.ceo/api/breed/${breed}/images/random`),
[]
);
const randomDogRecord = useLoads('functionVariables', getRandomDogByBreed, {
variables: [breed]
});
return (
{randomDogRecord.isPending && }
{randomDogRecord.isResolved && (
)}
{randomDogRecord.isRejected && {randomDogRecord.error.message}}
);
}
return ;
})
.add('with function variables (deferred)', () => {
function Component() {
const getRandomDogByBreed = React.useCallback(
breed => axios.get(`https://dog.ceo/api/breed/${breed}/images/random`),
[]
);
const randomDogRecord = useDeferredLoads('functionVariables', getRandomDogByBreed);
return (
{randomDogRecord.isIdle && }
{randomDogRecord.isPending && }
{randomDogRecord.isResolved && (
)}
{randomDogRecord.isRejected && {randomDogRecord.error.message}}
);
}
return ;
})
.add('suspense', () => {
function Component() {
const getRandomDog = React.useCallback(() => axios.get('https://dog.ceo/api/breeds/image/random'), []);
const randomDogRecord = useLoads('suspense', getRandomDog, { suspense: true });
return (
{randomDogRecord.isResolved && (
)}
{randomDogRecord.isRejected && {randomDogRecord.error.message}}
);
}
return (
}>
);
})
.add('custom delay', () => {
function Component() {
const getRandomDog = React.useCallback(() => axios.get('https://dog.ceo/api/breeds/image/random'), []);
const randomDogRecord = useDeferredLoads(getRandomDog, {
delay: 1000
});
return (
{randomDogRecord.isIdle && }
{randomDogRecord.isPending && }
{randomDogRecord.isResolved && (
)}
{randomDogRecord.isRejected && {randomDogRecord.error.message}}
);
}
return ;
})
.add('no delay', () => {
function Component() {
const getRandomDog = React.useCallback(() => axios.get('https://dog.ceo/api/breeds/image/random'), []);
const randomDogRecord = useDeferredLoads(getRandomDog, {
delay: 0
});
return (
{randomDogRecord.isIdle && }
{randomDogRecord.isPending && }
{randomDogRecord.isResolved && (
)}
{randomDogRecord.isRejected && {randomDogRecord.error.message}}
);
}
return ;
})
.add('with error', () => {
function Component() {
const getRandomDog = React.useCallback(() => axios.get('https://dog.ceo/api/breeds/sssss/random'), []);
const randomDogRecord = useDeferredLoads(getRandomDog, {
delay: 1000
});
return (
{randomDogRecord.isIdle && }
{randomDogRecord.isPending && }
{randomDogRecord.isResolved && (
)}
{randomDogRecord.isRejected && {randomDogRecord.error.message}}
);
}
return ;
})
.add('with timeout', () => {
function Component() {
const fn = React.useCallback(() => new Promise(res => setTimeout(() => res('this is data'), 2000)), []);
const randomDogRecord = useDeferredLoads(fn, {
timeout: 1000
});
return (
{randomDogRecord.isIdle && }
{(randomDogRecord.isPending || randomDogRecord.isPendingSlow) && }
{randomDogRecord.isPendingSlow && 'taking a while'}
{randomDogRecord.isResolved && {randomDogRecord.response}}
);
}
return ;
})
.add('with dependant useLoads', () => {
function Component({ movieId }) {
const getMovie = React.useCallback(async movieId => {
const movie = await api.getMovie(movieId);
return movie;
}, []);
const movieRecord = useLoads('movie', getMovie, { variables: [movieId] });
const movie = movieRecord.response;
const getReviews = React.useCallback(async movieId => {
const reviews = await api.getReviewsByMovieId(movieId);
return reviews;
}, []);
const reviewsRecord = useLoads('reviews', getReviews, { variables: () => [movie.id] });
const reviews = reviewsRecord.response;
return (
{movieRecord.isPending && }
{movieRecord.isResolved && (
Title: {movie.title}
{reviewsRecord.isResolved && reviews.map(review => review.comment)}
)}
);
}
return ;
})
.add('with dependant useLoads (deferred)', () => {
function Component() {
const getRandomDog = React.useCallback(() => axios.get('https://dog.ceo/api/breeds/image/random'), []);
const randomDogRecord = useLoads('dependant', getRandomDog, { defer: true });
const saveDog = React.useCallback(async imageSrc => new Promise(res => res(`Saved. Image: ${imageSrc}`)), []);
const saveDogRecord = useDeferredLoads(saveDog, {
variables: () => [randomDogRecord.response.data.message]
});
return (
{randomDogRecord.isIdle && }
{randomDogRecord.isPending && }
{randomDogRecord.isResolved && (
{randomDogRecord.response && (
)}
{saveDogRecord.isIdle && (
)}
{saveDogRecord.isResolved && {saveDogRecord.response}}
)}
{randomDogRecord.isRejected && {randomDogRecord.error.message}}
);
}
return ;
})
.add('with inputs', () => {
function Component() {
const [breed, setBreed] = useState('dingo');
const getRandomDogByBreed = React.useCallback(
() => axios.get(`https://dog.ceo/api/breed/${breed}/images/random`),
[breed]
);
const randomDogRecord = useLoads('inputs', getRandomDogByBreed);
return (
{randomDogRecord.isPending && }
{randomDogRecord.isResolved && (
)}
{randomDogRecord.isRejected && {randomDogRecord.error.message}}
);
}
return ;
})
.add('with update fn', () => {
function Component() {
const getRandomDog = React.useCallback(() => axios.get('https://dog.ceo/api/breeds/image/random'), []);
const getRandomDoberman = React.useCallback(
() => axios.get('https://dog.ceo/api/breed/doberman/images/random'),
[]
);
const randomDogRecord = useLoads('updateFn', getRandomDog, {
update: getRandomDoberman
});
return (
{randomDogRecord.isPending && }
{randomDogRecord.isResolved && (
)}
);
}
return ;
})
.add('with update fns', () => {
function Component() {
const getRandomDog = React.useCallback(() => axios.get('https://dog.ceo/api/breeds/image/random'), []);
const getRandomDoberman = React.useCallback(
() => axios.get('https://dog.ceo/api/breed/doberman/images/random'),
[]
);
const getRandomPoodle = React.useCallback(() => axios.get('https://dog.ceo/api/breed/poodle/images/random'), []);
const randomDogRecord = useLoads('updateFns', getRandomDog, {
update: [getRandomDoberman, getRandomPoodle]
});
const [loadDoberman, loadPoodle] = randomDogRecord.update;
return (
{randomDogRecord.isPending && }
{randomDogRecord.isResolved && (
)}
);
}
return ;
})
.add('with optimistic updates', () => {
function Component({ movieId }) {
const [ratingValue, setRatingValue] = React.useState();
const getMovie = React.useCallback(() => api.getMovie(movieId), [movieId]);
const movieRecord = useLoads('movie', getMovie);
const movie = movieRecord.response || {};
const updateMovie = React.useCallback(
() => meta => {
meta.setResponse(movie => ({ ...movie, imdbRating: ratingValue }));
return api.updateMovie(movieId, { imdbRating: ratingValue });
},
[movieId, ratingValue]
);
const updateMovieRecord = useDeferredLoads('movie', updateMovie);
return (
{movieRecord.isPending && }
{movieRecord.isResolved && (
{movie.title}
Rating: {movie.imdbRating}
setRatingValue(e.target.value)}
placeholder="Enter new rating"
value={ratingValue}
/>
)}
{movieRecord.isRejected && {movieRecord.error.message}}
);
}
return ;
})
.add('with onResolve', () => {
function Component() {
const getRandomDog = React.useCallback(() => axios.get('https://dog.ceo/api/breeds/image/random'), []);
const onResolve = React.useCallback(record => console.log('success', record), []);
const randomDogRecord = useLoads('basic', getRandomDog, { onResolve });
return (
{randomDogRecord.isPending && }
{randomDogRecord.isResolved && (
)}
{randomDogRecord.isRejected && {randomDogRecord.error.message}}
);
}
return ;
})
.add('with onReject', () => {
function Component() {
const getSomething = React.useCallback(async () => {
return new Promise((res, rej) => setTimeout(() => rej(new Error('This is an error.')), 1000));
}, []);
const onReject = React.useCallback(error => console.log('error', error), []);
const somethingRecord = useLoads('rejectHook', getSomething, { onReject });
return (
{somethingRecord.isPending && }
{somethingRecord.isRejected && {somethingRecord.error.message}}
);
}
return ;
})
.add('with revalidateTime', () => {
function Component() {
const getRandomDog = React.useCallback(() => axios.get('https://dog.ceo/api/breeds/image/random'), []);
const randomDogRecord = useLoads('revalidateTime', getRandomDog, {
revalidateTime: 5000,
loadPolicy: 'cache-first'
});
return (
{randomDogRecord.isPending && }
{randomDogRecord.isResolved && (
)}
{randomDogRecord.isRejected && {randomDogRecord.error.message}}
);
}
return ;
})
.add('with cacheTime', () => {
function Component() {
const getRandomDog = React.useCallback(() => axios.get('https://dog.ceo/api/breeds/image/random'), []);
const randomDogRecord = useLoads('cacheTime', getRandomDog, {
cacheTime: 5000
});
return (
{randomDogRecord.isPending && }
{randomDogRecord.isResolved && (
)}
{randomDogRecord.isRejected && {randomDogRecord.error.message}}
);
}
return ;
})
.add('with dedupingInterval', () => {
function Component() {
const getRandomDog = React.useCallback(() => axios.get('https://dog.ceo/api/breeds/image/random'), []);
const randomDogRecord = useLoads('dedupingInterval', getRandomDog, {
dedupingInterval: 2000
});
return (
{randomDogRecord.isPending && }
{randomDogRecord.isResolved && (
)}
{randomDogRecord.isRejected && {randomDogRecord.error.message}}
);
}
return ;
})
.add('with debounce', () => {
function Component() {
const [value, setValue] = React.useState('poodle');
const getRandomDog = React.useCallback(
({ value }) => axios.get(`https://dog.ceo/api/breed/${value}/images/random`),
[]
);
const randomDogRecord = useLoads('debounce', getRandomDog, {
debounce: 1000,
variables: [{ value }]
});
return (
setValue(e.target.value)} value={value} />
{randomDogRecord.isPending && }
{randomDogRecord.isResolved &&
randomDogRecord.response && (
)}
{randomDogRecord.isRejected && {randomDogRecord.error.message}}
);
}
return ;
})
.add('with pollingInterval', () => {
function Component() {
const getRandomDog = React.useCallback(() => axios.get('https://dog.ceo/api/breeds/image/random'), []);
const randomDogRecord = useLoads('pollingInterval', getRandomDog, {
pollingInterval: 2000
});
return (
{randomDogRecord.isPending && }
{randomDogRecord.isResolved && (
)}
{randomDogRecord.isRejected && {randomDogRecord.error.message}}
);
}
return ;
})
.add('with rejectRetryInterval', () => {
function Component() {
const getRandomDog = React.useCallback(() => axios.get('https://dog.ceo/api/breeds/sssss/random'), []);
const randomDogRecord = useDeferredLoads(getRandomDog, {
rejectRetryInterval: 5000
});
return (
{randomDogRecord.isIdle && }
{randomDogRecord.isPending && }
{randomDogRecord.isResolved && (
)}
{randomDogRecord.isRejected && {randomDogRecord.error.message}}
);
}
return ;
})
.add('with rejectRetryInterval (function)', () => {
function Component() {
const getRandomDog = React.useCallback(() => axios.get('https://dog.ceo/api/breeds/sssss/random'), []);
const randomDogRecord = useDeferredLoads(getRandomDog, {
rejectRetryInterval: count => count * 5000
});
return (
{randomDogRecord.isIdle && }
{randomDogRecord.isPending && }
{randomDogRecord.isResolved && (
)}
{randomDogRecord.isRejected && {randomDogRecord.error.message}}
);
}
return ;
})
.add('with load-only loadPolicy', () => {
function Component() {
const getRandomDog = React.useCallback(() => axios.get('https://dog.ceo/api/breeds/image/random'), []);
const randomDogRecord = useLoads('loadOnly', getRandomDog, { loadPolicy: 'load-only' });
return (
{randomDogRecord.isPending && }
{randomDogRecord.isResolved && (
)}
{randomDogRecord.isRejected && {randomDogRecord.error.message}}
);
}
return ;
})
.add('with cache-and-load loadPolicy', () => {
function Component() {
const getRandomDog = React.useCallback(() => axios.get('https://dog.ceo/api/breeds/image/random'), []);
const randomDogRecord = useLoads('cacheAndLoad', getRandomDog, { loadPolicy: 'cache-and-load' });
return (
{randomDogRecord.isPending && }
{randomDogRecord.isResolved && (
)}
{randomDogRecord.isRejected && {randomDogRecord.error.message}}
);
}
return ;
})
.add('with cache-first loadPolicy', () => {
function Component() {
const getRandomDog = React.useCallback(() => axios.get('https://dog.ceo/api/breeds/image/random'), []);
const randomDogRecord = useLoads('cacheFirst', getRandomDog, { loadPolicy: 'cache-first' });
return (
{randomDogRecord.isPending && }
{randomDogRecord.isResolved && (
)}
{randomDogRecord.isRejected && {randomDogRecord.error.message}}
);
}
return ;
})
.add('with key-only cacheStrategy', () => {
function Component() {
const [breed, setBreed] = React.useState('beagle');
const getRandomDogByBreed = React.useCallback(
breed => axios.get(`https://dog.ceo/api/breed/${breed}/images/random`),
[]
);
const randomDogRecord = useLoads('functionVariables', getRandomDogByBreed, {
cacheStrategy: 'key-only',
variables: [breed]
});
return (
{randomDogRecord.isPending && }
{randomDogRecord.isResolved && (
)}
{randomDogRecord.isRejected && {randomDogRecord.error.message}}
);
}
return ;
})
.add('with initialResponse', () => {
function Component() {
const getRandomDog = React.useCallback(() => axios.get('https://dog.ceo/api/breeds/image/random'), []);
const randomDogRecord = useLoads('basic', getRandomDog, {
initialResponse: { data: { message: 'https://images.dog.ceo/breeds/schnauzer-miniature/n02097047_2002.jpg' } }
});
return (
{randomDogRecord.isPending && }
{randomDogRecord.isResolved && (
)}
{randomDogRecord.isRejected && {randomDogRecord.error.message}}
);
}
return ;
});
storiesOf('useCache', module).add('cache', () => {
function Component() {
const getRandomDog = React.useCallback(() => axios.get('https://dog.ceo/api/breeds/image/random'), []);
const randomDogRecord = useDeferredLoads('basic', getRandomDog);
return (
{randomDogRecord.isIdle && }
{randomDogRecord.isPending && }
{randomDogRecord.isResolved && (
)}
{randomDogRecord.isRejected && {randomDogRecord.error.message}}
);
}
function Cache() {
const randomDogRecord = useCache('basic');
if (randomDogRecord && randomDogRecord.response) {
return (
Cached:
);
}
return null;
}
return (
);
});
storiesOf('useGetStates', module).add('basic', () => {
function Component() {
const getSomething = React.useCallback(async () => {
return new Promise(res => setTimeout(() => res('This is something.'), 1000));
}, []);
const somethingRecord = useLoads('something', getSomething);
const getAnother = React.useCallback(async () => {
return new Promise(res => setTimeout(() => res('This is another.'), 5000));
}, []);
const anotherRecord = useLoads('another', getAnother, { timeout: 3000 });
const states = useGetStates(somethingRecord, anotherRecord);
return (
{states.isPending && 'Pending...'}
{states.isPendingSlow && ' Taking a while...'}
{states.isResolved && `Both records have resolved. ${somethingRecord.response} ${anotherRecord.response}`}
);
}
return ;
});
storiesOf('cache', module).add('cache.clear', () => {
function Component() {
return (
);
}
return ;
});