Skip to content

Commit

Permalink
Merge 51295bb into b80e82c
Browse files Browse the repository at this point in the history
  • Loading branch information
spautz committed Aug 15, 2020
2 parents b80e82c + 51295bb commit 1fc5cf6
Show file tree
Hide file tree
Showing 7 changed files with 232 additions and 100 deletions.
7 changes: 6 additions & 1 deletion .storybook/main.js
Expand Up @@ -4,7 +4,12 @@ module.exports = {
"../packages/*/stories/**/*.stories.@(js|jsx|ts|tsx)"
],
"addons": [
'@storybook/addon-actions',
"@storybook/addon-links",
"@storybook/addon-essentials"
]
],
webpackFinal: async (config) => {
config.performance.hints = false;
return config;
},
}
4 changes: 3 additions & 1 deletion package.json
Expand Up @@ -29,6 +29,8 @@
"packages:dev": "lerna exec yon dev",
"packages:all": "lerna exec yon all",
"____ INDIVIDUAL COMMANDS ___________________________________________": "",
"demo:prepare": "yarn install && yarn build-storybook",
"demo:deploy": "gh-pages -d ./storybook-static",
"format": "prettier --write \"**/*.*\"",
"format:checkup": "prettier --list-different \"**/*.*\"",
"lint": "eslint \"**/*.{js,jsx,json,ts,tsx}\"",
Expand All @@ -49,7 +51,6 @@
"@babel/preset-typescript": "^7.10.4",
"@storybook/addon-actions": "^6.0.10",
"@storybook/addon-essentials": "^6.0.10",
"@storybook/addon-knobs": "^6.0.10",
"@storybook/addon-links": "^6.0.10",
"@storybook/react": "^6.0.10",
"@testing-library/jest-dom": "^5.11.3",
Expand All @@ -68,6 +69,7 @@
"eslint-plugin-prettier": "^3.1.4",
"eslint-plugin-react": "^7.20.6",
"fork-ts-checker-webpack-plugin": "^5.0.14",
"gh-pages": "^3.1.0",
"husky": "^4.2.5",
"jest": "^26.4.0",
"lerna": "^3.22.1",
Expand Down
19 changes: 17 additions & 2 deletions packages/dev-helpers/src/components/DemoContainer.tsx
Expand Up @@ -11,14 +11,17 @@ import { incrementAction, DevHelperState } from '../redux';
export interface DemoContainerProps {
title: string;
withRedux?: boolean;
onMount?: (instanceTitle: string) => void;
onRender?: (instanceTitle: string) => void;
onUnmount?: (instanceTitle: string) => void;
}

const selectEntireState = (state: DevHelperState): DevHelperState => state;

let totalInstanceCount = 0;

const DemoContainer: React.FC<DemoContainerProps> = (props: DemoContainerProps): ReactElement => {
const { title, withRedux } = props;
const { title, withRedux, onMount, onRender, onUnmount } = props;

// A simple per-Component instance counter
const myInstanceNumRef = React.useRef(0);
Expand All @@ -35,11 +38,23 @@ const DemoContainer: React.FC<DemoContainerProps> = (props: DemoContainerProps):

React.useEffect((): (() => void) => {
console.log(`DemoContainer ${titleWithMyInstanceNum} mounted`);
return (): void => console.log(`DemoContainer ${titleWithMyInstanceNum} unmounted`);
if (onMount) {
// Wait an extra tick for Storybook to catch up, or else actions won't be logged
setTimeout(() => onMount(titleWithMyInstanceNum));
}
return (): void => {
console.log(`DemoContainer ${titleWithMyInstanceNum} unmounted`);
if (onUnmount) {
setTimeout(() => onUnmount(titleWithMyInstanceNum));
}
};
}, []);

React.useEffect(() => {
console.log(`DemoContainer ${titleWithMyInstanceNum} rendered`);
if (onRender) {
onRender(titleWithMyInstanceNum);
}
});

// Our own local state
Expand Down
5 changes: 2 additions & 3 deletions packages/react-hibernate/stories/index.stories.tsx
@@ -1,6 +1,5 @@
import * as React from 'react';
import { ReactNode } from 'react';
import { withKnobs } from '@storybook/addon-knobs';

import 'typeface-roboto';

Expand All @@ -9,9 +8,9 @@ import { DemoContainer } from 'react-hibernate-dev-helpers';
import { HibernationProvider, HibernatingSubtree } from '../src';

export default {
title: 'Basic usage',
title: 'React Hibernate (unreleased)',
component: HibernationProvider,
decorators: [withKnobs],
decorators: [],
};

export const Default = (): ReactNode => {
Expand Down
@@ -1,5 +1,4 @@
import React, { ReactNode, useCallback, useState } from 'react';
import { withKnobs } from '@storybook/addon-knobs';

import Button from '@material-ui/core/Button';
import Chip from '@material-ui/core/Chip';
Expand All @@ -15,7 +14,12 @@ import ReduxMonitor from './ReduxMonitor';

export default {
title: 'React Pauseable Containers',
decorators: [reduxDecorator, withKnobs],
decorators: [reduxDecorator],
parameters: {
options: {
showPanel: false,
},
},
};

export const PauseableComponentContainerStory = (): ReactNode => {
Expand All @@ -29,7 +33,7 @@ export const PauseableComponentContainerStory = (): ReactNode => {
<code>&lt;PauseableComponentContainer&gt;</code>
</Typography>
<Typography variant="subtitle1">
The parent state includes a <code>count</code> variable which is passed to each child.
The parent state has a <code>count</code>, which gets passed to each child.
</Typography>
<Typography variant="subtitle1">
Each child is wrapped in a <code>PauseableComponentContainer</code> whose{' '}
Expand All @@ -48,7 +52,7 @@ export const PauseableComponentContainerStory = (): ReactNode => {
</div>
);
};
PauseableComponentContainerStory.story = { name: 'PauseableComponentContainer' };
PauseableComponentContainerStory.storyName = 'PauseableComponentContainer';

const PauseableReduxContainerDemo = () => {
return (
Expand All @@ -57,7 +61,7 @@ const PauseableReduxContainerDemo = () => {
<code>&lt;PauseableReduxContainer&gt;</code>
</Typography>
<Typography variant="subtitle1">
The parent state includes a <code>count</code> variable which is passed to each child.
Redux state has a <code>count</code>, which each child displays.
</Typography>
<Typography variant="subtitle1">
Each child is wrapped in a <code>PauseableReduxContainer</code> whose{' '}
Expand All @@ -76,10 +80,8 @@ const PauseableReduxContainerDemo = () => {
export const PauseableReduxContainerStory = (): ReactNode => {
return <PauseableReduxContainerDemo />;
};
PauseableReduxContainerStory.story = {
name: 'PauseableReduxContainer',
decorators: [reduxDecorator],
};
PauseableReduxContainerStory.storyName = 'PauseableReduxContainer';
PauseableReduxContainerStory.decorators = [reduxDecorator];

// @TODO: A story where the PauseableReduxItems can dispatch actions
// const dispatchWhenPaused = boolean('Allow dispatches from paused children', false);
90 changes: 65 additions & 25 deletions packages/react-router-hibernate/stories/index.stories.tsx
Expand Up @@ -3,23 +3,38 @@ import { ReactElement, ReactNode } from 'react';
import { MemoryRouter, Redirect, Route, RouteProps } from 'react-router';
import { NavLink } from 'react-router-dom';
import Typography from '@material-ui/core/Typography';
import { withKnobs, number } from '@storybook/addon-knobs';
import { action } from '@storybook/addon-actions';

import 'typeface-roboto';

import { DemoContainer } from 'react-hibernate-dev-helpers';

import { HibernatingRoute, HibernatingSwitch } from '../src';
import { HibernatingRoute, HibernatingSwitch, HibernatingSwitchProps } from '../src';

export default {
title: 'Basic usage',
title: 'React Router Hibernate',
component: HibernatingSwitch,
decorators: [withKnobs],
decorators: [],
parameters: {
options: {
showPanel: true,
},
},
};

export const MaxCacheTimeOneMinute = (): ReactNode => {
const maxCacheSize = number('maxCacheSize', -1);
const maxCacheTime = number('maxCacheTime', 60 * 1000);
const storyArgTypes = {
maxCacheSize: { control: { type: 'range', min: 0, max: 10, step: 1 } },
maxCacheTime: { control: { type: 'range', min: 0, max: 600 * 1000, step: 1000 } },
WrapperComponent: { control: { disable: true } },
};

const logMountAction = action('mount');
const logUnmountAction = action('unmount');

// maxCacheTime: starts with an infinite cache size and a short cache time

export const MaxCacheTimeStory = (args: HibernatingSwitchProps): ReactNode => {
const { maxCacheSize, maxCacheTime } = args;

return (
<MemoryRouter initialEntries={['/route1']}>
Expand All @@ -34,27 +49,35 @@ export const MaxCacheTimeOneMinute = (): ReactNode => {
<NavLink to="/route3/3">Route3 id=3</NavLink>

<Typography variant="subtitle1">
After leaving a screen, its state will be retained for one minute
After leaving a screen, its state will be retained for ten seconds. Use the maxCacheTime
control to set any time up to ten minutes.
</Typography>

<HibernatingSwitch maxCacheSize={maxCacheSize} maxCacheTime={maxCacheTime}>
<HibernatingRoute path="/route1">
<DemoContainer title="Route 1" />
<DemoContainer title="Route 1" onMount={logMountAction} onUnmount={logUnmountAction} />
</HibernatingRoute>
<HibernatingRoute path="/route2">
<DemoContainer title="Route 2" />
<DemoContainer title="Route 2" onMount={logMountAction} onUnmount={logUnmountAction} />
</HibernatingRoute>
<HibernatingRoute path="/route3/:id">
<DemoContainer title="Route 3" />
<DemoContainer title="Route 3" onMount={logMountAction} onUnmount={logUnmountAction} />
</HibernatingRoute>
</HibernatingSwitch>
</MemoryRouter>
);
};
MaxCacheTimeStory.storyName = 'maxCacheTime';
MaxCacheTimeStory.args = {
maxCacheSize: 0,
maxCacheTime: 10 * 1000,
};
MaxCacheTimeStory.argTypes = storyArgTypes;

// maxCacheTime: starts with a cache size of 1 and an infinite cache time

export const MaxCacheSizeOne = (): ReactNode => {
const maxCacheSize = number('maxCacheSize', 1);
const maxCacheTime = number('maxCacheTime', -1);
export const MaxCacheSizeStory = (args: HibernatingSwitchProps): ReactNode => {
const { maxCacheSize, maxCacheTime } = args;

return (
<MemoryRouter initialEntries={['/route1']}>
Expand All @@ -68,28 +91,38 @@ export const MaxCacheSizeOne = (): ReactNode => {
{' | '}
<NavLink to="/route3/3">Route3 id=3</NavLink>

<Typography variant="subtitle1">Only the last screen you visited will be retained</Typography>
<Typography variant="subtitle1">
Only the last screen you visited will be retained. Use the maxCacheSize control to set the
number of screens to retain.
</Typography>

<HibernatingSwitch maxCacheSize={maxCacheSize} maxCacheTime={maxCacheTime}>
<HibernatingRoute path="/route1">
<DemoContainer title="Route 1" />
<DemoContainer title="Route 1" onMount={logMountAction} onUnmount={logUnmountAction} />
</HibernatingRoute>
<HibernatingRoute path="/route2">
<DemoContainer title="Route 2" />
<DemoContainer title="Route 2" onMount={logMountAction} onUnmount={logUnmountAction} />
</HibernatingRoute>
<HibernatingRoute path="/route3/:id">
<DemoContainer title="Route 3" />
<DemoContainer title="Route 3" onMount={logMountAction} onUnmount={logUnmountAction} />
</HibernatingRoute>
</HibernatingSwitch>
</MemoryRouter>
);
};
MaxCacheSizeStory.storyName = 'maxCacheSize';
MaxCacheSizeStory.args = {
maxCacheSize: 1,
maxCacheTime: 0,
};
MaxCacheSizeStory.argTypes = storyArgTypes;

// Mix and match

const MyCustomRoute = (props: RouteProps): ReactElement => <Route {...props} />;

export const MixRoutesAndHibernatingRoutes = (): ReactNode => {
const maxCacheSize = number('maxCacheSize', 0);
const maxCacheTime = number('maxCacheTime', 0);
export const MixedRouteTypesStory = (args: HibernatingSwitchProps): ReactNode => {
const { maxCacheSize, maxCacheTime } = args;

return (
<MemoryRouter initialEntries={['/not-matched']}>
Expand All @@ -104,21 +137,28 @@ export const MixRoutesAndHibernatingRoutes = (): ReactNode => {
<NavLink to="/route3/3">Hibernating id=3</NavLink>

<Typography variant="subtitle1">
The first two screens are never retained, the last three are
The first two screens are never hibernated/restored, the last three are. Use the controld to
adjust settings.
</Typography>

<HibernatingSwitch maxCacheSize={maxCacheSize} maxCacheTime={maxCacheTime}>
<Route path="/route1">
<DemoContainer title="Route 1" />
<DemoContainer title="Route 1" onMount={logMountAction} onUnmount={logUnmountAction} />
</Route>
<MyCustomRoute path="/route2">
<DemoContainer title="Route 2" />
<DemoContainer title="Route 2" onMount={logMountAction} onUnmount={logUnmountAction} />
</MyCustomRoute>
<HibernatingRoute path="/route3/:id">
<DemoContainer title="Route 3" />
<DemoContainer title="Route 3" onMount={logMountAction} onUnmount={logUnmountAction} />
</HibernatingRoute>
<Redirect to="/route1" />
</HibernatingSwitch>
</MemoryRouter>
);
};
MixedRouteTypesStory.storyName = 'Mixed route types';
MixedRouteTypesStory.args = {
maxCacheSize: 5,
maxCacheTime: 60 * 1000,
};
MixedRouteTypesStory.argTypes = storyArgTypes;

0 comments on commit 1fc5cf6

Please sign in to comment.