Skip to content

Instantly share code, notes, and snippets.

@undoZen
Created April 28, 2020 09:11
Show Gist options
  • Save undoZen/a5bc6eed6331fb038f1ea4c576b61b5d to your computer and use it in GitHub Desktop.
Save undoZen/a5bc6eed6331fb038f1ea4c576b61b5d to your computer and use it in GitHub Desktop.
import React, { memo, Suspense } from 'react';
import { of, from, pipe } from 'rxjs';
import { map, switchMap, pluck } from 'rxjs/operators';
import { createRxContainer, LOADING } from '@/utils/unstated-rxjs';
import { tapLog } from '@/utils/operators';
const delay = (value: any, waitMs: number) =>
new Promise(resolve => {
setTimeout(() => resolve(value), waitMs);
});
const delayNow = (waitMs: number) =>
new Promise(resolve => {
setTimeout(() => resolve(Date.now()), waitMs);
});
const ABContainer = createRxContainer(inputs$ => {
const operator = prop =>
pipe(
pluck(prop),
switchMap(([value, wait]) =>
wait ? from(delay(value, wait)) : of(value),
),
);
return {
a: inputs$.pipe(operator('a')),
b: inputs$.pipe(operator('b')),
};
});
const ABCDContainer = createRxContainer((inputs$, observables, subjects) => {
const operator = prop =>
pipe(
pluck(prop),
switchMap(wait => (wait ? from(delayNow(wait)) : of(Date.now()))),
);
return {
a: observables.a.pipe(
tapLog('aaa'),
map(x => x * 100),
),
/*
b: observables.b.pipe(
tapLog('bbb'),
map(x => x * 10000),
),
*/
c: inputs$.pipe(operator('c')),
d: inputs$.pipe(operator('d')),
};
}, ABContainer);
const Loading = () => <span>loading...</span>;
const SaySay = memo(function SaySay() {
console.log('render SaySay');
const ctx = ABContainer.useContext();
return (
<>
hello, {ctx.a} and {ctx.b}
</>
);
});
const SayHello = memo(function SayHello({ children }) {
console.log('render SayHello');
return (
<div>
<Suspense fallback={<Loading />}>
<SaySay />
</Suspense>
{children}
</div>
);
});
const HelloHello = memo(function HelloHello() {
console.log('render HelloHello');
const ctx = ABCDContainer.useContext();
console.log('try to read ctx');
console.log(ctx.a, ctx.b, typeof ctx.a, typeof ctx.b);
return (
<div>
hello, {ctx.a} and {ctx.b}
hi, {ctx.c} and {ctx.d}
</div>
);
});
const inputsA = { a: [1, 2000], b: [2] };
const inputsB = { a: [1, 5000], b: [2, 3000] };
const inputsCD = { c: 6000, d: 5500 };
const Page = memo(function Page() {
console.log('render');
return (
<>
<ABContainer.Provider inputs={inputsA}>
<Suspense fallback={<Loading />}>
<SayHello />
</Suspense>
</ABContainer.Provider>
<ABContainer.Provider inputs={inputsB}>
<Suspense fallback={<Loading />}>
<SayHello>
<ABCDContainer.Provider inputs={inputsCD}>
<Suspense fallback={<Loading />}>
<HelloHello />
</Suspense>
</ABCDContainer.Provider>
</SayHello>
</Suspense>
</ABContainer.Provider>
</>
);
});
export default Page;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment