Last active
March 10, 2023 16:26
-
-
Save darcher-/9a86f8f069c102468911f38e03f623c3 to your computer and use it in GitHub Desktop.
Structured lazy dynamic imports - serve only what is required.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { lazy } from "react"; | |
/** | |
* use dynamic "code-splitting" imports | |
* prevents all components from being bundled and loaded at runtime | |
* only serves what is being utilized at render | |
*/ | |
class DynamicComponent { | |
private _node = { | |
tricky: lazy(() => import("./dynamic-prop-state-management")), | |
simple: lazy(() => import("./runtime-prop-state-management")), | |
loader: lazy(() => import("./icon-loader")), | |
}; | |
getElement() { | |
return { | |
Tricky: this._node.tricky, | |
Loader: this._node.loader, | |
Simple: this._node.simple, | |
}; | |
} | |
} | |
const Component = new DynamicComponent().getElement(); | |
//? export individually | |
export const Tricky = Component.Tricky; | |
export const Loader = Component.Loader; | |
export const Simple = Component.Simple; | |
//? pass all methods to default export | |
export default { ...Component } as const; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* only call what is needed | |
* avoid using: | |
* - import React from 'react' | |
* - import * as React from 'react' | |
*/ | |
import { | |
Fragment, | |
Suspense, | |
memo, | |
useId, | |
useRef, | |
useEffect, | |
useReducer, | |
} from "react"; | |
//? call only what is used | |
import { Loader } from "src/components"; | |
//? memoize components where able | |
export default memo((props: { running: boolean; time: number; }) => { | |
//? dynamic props that rely on each other should utilize useReducer call | |
const [state, dispatch] = useReducer< | |
{ running: boolean; time: number; }, | |
{ type: "reset" | "start" | "stop" | "tick"; }, | |
//TODO: if reused, hoist to type or abstract to types.d file | |
{ running: boolean; time: number; } | |
//TODO: the first argument can be abstracted to utilities if used frequently | |
>((state, action) => { | |
switch (action.type) { | |
case "start": { return { ...state, running: true } }; | |
case "stop": { return { ...state, running: false } }; | |
case "tick": { return { ...state, time: state.time + 1 } }; | |
case "reset": { return { running: false, time: 0 } }; | |
default: { throw new Error("I broked it!") }; | |
} | |
}, props); | |
const ref: { current: number } = useRef(0); | |
useEffect((): void | { (): void } => { | |
if (state.running) { | |
ref.current = setInterval( | |
() => dispatch({ type: "tick" }), | |
1000 | |
); | |
return () => { | |
clearInterval(ref.current); | |
ref.current = 0; | |
}; | |
} | |
}, [state.running]); | |
return ( | |
{/*? use Suspense fallback to indicate load state*/} | |
<Suspense fallback={<Loader />}> | |
{/*? assign unique id to Fragment key */} | |
<Fragment key={useId()}> | |
<p className={`timespan`}> | |
<strong>{state.time}s</strong> | |
</p> | |
<div className={`actions`}> | |
<button onClick={() => dispatch({ type: "start" })}>Start</button> | |
<button onClick={() => dispatch({ type: "stop" })}>Stop</button> | |
<button onClick={() => dispatch({ type: "reset" })}>Reset</button> | |
</div> | |
</Fragment> | |
</Suspense> | |
); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* only call what is needed | |
* avoid using: | |
* - import React from 'react' | |
* - import * as React from 'react' | |
*/ | |
import { Fragment, memo, useId } from "react"; | |
//? memoize components where able | |
export default memo(() => { | |
return ( | |
{/*? assign unique id to Fragment key */} | |
<Fragment key={useId()}> | |
<svg | |
className={`icon icon-loader`} | |
fill={`currentColor`} | |
{/*? always make svg elements unfocusable */} | |
focusable={true} | |
height={64} | |
{/*? assign as role="img" or aria-hidden="true" depending on need */} | |
role={`img`} | |
width={64} | |
viewBox={`0 0 50 50`} | |
> | |
<path | |
d={` | |
M25,5A20.14,20.14,0,0,1,45,22.88a2.51,2.51,0,0,0, | |
2.49,2.26h0A2.52,2.52,0,0,0,50,22.33a25.14,25.14, | |
0,0,0-50,0,2.52,2.52,0,0,0,2.5,2.81h0A2.51,2.51, | |
0,0,0,5,22.88,20.14,20.14,0,0,1,25,5Z | |
`} | |
> | |
<animateTransform | |
attributeName={`transform`} | |
type={`rotate`} | |
from={`0 25 25`} | |
to={`360 25 25`} | |
dur={`0.5s`} | |
repeatCount={`indefinite`} | |
/> | |
</path> | |
</svg> | |
</Fragment> | |
); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { StrictMode, Suspense } from "react"; | |
import { createRoot } from "react-dom/client"; | |
//? we use all components; so we can namespace it | |
import Component from "./components"; | |
//TODO: this should be abstracted to fixtures | |
const CPROPS = { running: false, time: 0 }; | |
const SPROPS = { name: "Spot", age: 13, type: "dog" }; | |
createRoot(document.getElementById("root")! as HTMLElement).render( | |
{/*? always utilize strict mode */} | |
<StrictMode> | |
{/*? use Suspense fallback to indicate load state*/} | |
<Suspense fallback={<Component.Loader />}> | |
{/*? when not in Function Component we can use Fragment shorthand */} | |
<> | |
<Component.Tricky {...CPROPS} /> | |
<Component.Simple {...SPROPS} /> | |
<Bad /> | |
<> | |
</Suspense> | |
</StrictMode> | |
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* only call what is needed | |
* avoid using: | |
* - import React from 'react' | |
* - import * as React from 'react' | |
*/ | |
import { | |
Fragment, | |
FunctionComponent, | |
Suspense, | |
memo, | |
useEffect, | |
useId, | |
useState, | |
} from "react"; | |
//? call only what is used | |
import { Loader } from "src/components"; | |
//? memoize components where able | |
export default memo((props: { | |
/** | |
* Explicitly define props; avoid dynamic typing (for now) | |
* e.g. this could easily be on of the following: | |
* - Partial<Record<string, string | number | boolean>> | |
* - Partial<{ [K: string]: string | number | boolean }> | |
* - { [K in 'name' | 'age' | 'elder' | 'title' | 'type']?: string | number | boolean } | |
*/ | |
name: string; | |
age: number; | |
elder?: boolean; | |
title?: string; | |
type: string; | |
}) => { | |
//? feed all props to single useState call | |
const [state, setState] = useState({ | |
...props, | |
elder: false, | |
}); | |
//? runtime updates | |
useEffect((): void => { | |
setState((etc) => ({ | |
...etc, | |
title: { | |
dog: "canine", | |
cat: "feline", | |
}[etc.type], | |
})); | |
}, [state.type]); | |
//? split updates into separate useEffect calls | |
useEffect((): void => { | |
setState((etc) => ({ | |
...etc, | |
elder: etc.age > 7, | |
})); | |
}, [state.elder]); | |
//* you can destructure state here if you'd prefer | |
return ( | |
{/*? use Suspense fallback to indicate load state*/} | |
<Suspense fallback={<Loader />}> | |
{/*? assign unique id to Fragment key */} | |
<Fragment key={useId()}> | |
<dl className={`pet`}> | |
<dt>Pet Name</dt> | |
<dd>{state.name}</dd> | |
<dt>Age</dt> | |
<dd>{state.age}</dd> | |
<dt>Status</dt> | |
<dd>{state.title} {state.elder ? `Elder` : `Pup`}</dd> | |
</dl> | |
</Fragment> | |
</Suspense> | |
); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment