-
Notifications
You must be signed in to change notification settings - Fork 0
/
Suspense.stories.tsx
109 lines (92 loc) · 2.64 KB
/
Suspense.stories.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
/** @jsxImportSource ../src */
import { Suspense } from 'react';
import { Meta, Story } from '@storybook/react';
import {effect, r, ref, watchEffect} from '../src';
interface Props {}
function getSuspendedValue() {
const { resolve, signal } = delay();
let value: string;
let isResolved = false;
setTimeout(() => {
value = 'Hello World';
isResolved = true;
resolve();
}, 1000);
return {
get current() {
if (!isResolved) {
throw signal;
}
return value;
},
};
}
function App() {
const message = getSuspendedValue();
const announcement = ref(`"Random" message of the day...`);
effect(function startTimer() {
setTimeout(() => {
announcement.current = 'Halfway there...';
}, 500);
});
return r(() => (
<div>
<h1>{announcement.current}</h1>
<Suspense fallback={<p>...wait for it.</p>}>
<Placeholder />
<Text message={message} />
<Placeholder />
</Suspense>
<Suspense fallback={<p>...wait for the loud version it.</p>}>
<LoudText message={message} />
</Suspense>
</div>
));
}
interface TextModel {
message: { current: string };
}
function Text({ message }: TextModel) {
console.log('Text: Mounting component');
watchEffect((onInvalidate) => {
console.log('Text: Starting expensive process...');
onInvalidate(() => console.log('Text: Expensive process cleaned up'));
});
return r(() => <p>{message.current}</p>);
}
function LoudText({ message }: TextModel) {
console.log(`LoudText: Mounting component`);
watchEffect((onInvalidate) => {
console.log('LoudText: Starting expensive process...');
onInvalidate(() => console.log('LoudText: Expensive process cleaned up'));
});
const loudMessage = message.current + '!';
return r(() => <p>{loudMessage}</p>);
}
function Placeholder() {
watchEffect(function logMounting(onInvalidate) {
console.log('Placeholder: Start');
onInvalidate(() => console.log(`Placeholder: Cleanup`));
});
return r(() => (
<p>Just some text</p>
));
}
function delay<T = any>() {
let resolve: (value?: T) => void = undefined as any;
const signal = new Promise(res => (resolve = res));
return { signal, resolve };
}
const meta: Meta<Props> = {
title: 'Suspense',
component: App,
parameters: {
controls: { expanded: true },
},
};
export default meta;
const Template: Story<Props> = args => <App {...args} />;
// By passing using the Args format for exported stories, you can control the props for a component for reuse in a test
// https://storybook.js.org/docs/react/workflows/unit-testing
export const Default = Template.bind({});
Default.args = {};