-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
FEI-5465.4: Lesson 2 - Prevent Context From Rerendering
- Loading branch information
1 parent
a7143c3
commit 853e0a3
Showing
19 changed files
with
371 additions
and
2 deletions.
There are no files selected for viewing
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import {fib} from "../../shared/fib"; | ||
import {Circle} from "../../shared/shapes"; | ||
|
||
type Props = { | ||
circle: Circle; | ||
onClick: () => void; | ||
}; | ||
|
||
export function ChildComponent({circle, onClick}: Props) { | ||
return ( | ||
<div> | ||
<h1>Child Component</h1> | ||
<p>fib(36) = {fib(36)}</p> | ||
<button onClick={onClick}>Click me!</button> | ||
<svg> | ||
<circle | ||
r={circle.radius} | ||
cx={circle.center.x} | ||
cy={circle.center.y} | ||
/> | ||
</svg> | ||
</div> | ||
); | ||
} |
10 changes: 10 additions & 0 deletions
10
src/react-render-perf/lesson-02/exercise/color-picker-context.tsx
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import {createContext} from "react"; | ||
|
||
import {Color} from "../../shared/color"; | ||
|
||
type Context = { | ||
color?: Color; | ||
setColor: (color?: Color) => void; | ||
}; | ||
|
||
export const ColorPickerContext = createContext<Context | null>(null); |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import {useState} from "react"; | ||
|
||
import {Grid} from "./grid"; | ||
import {ColorPickerContext} from "./color-picker-context"; | ||
import {Color, toCssColor} from "../../shared/color"; | ||
|
||
export function ColorPicker() { | ||
const [color, setColor] = useState<Color | undefined>(undefined); | ||
|
||
return ( | ||
<div> | ||
<ColorPickerContext.Provider value={{color, setColor}}> | ||
<Grid | ||
topLeft={{red: 0, green: 0, blue: 256}} | ||
topRight={{red: 256, green: 0, blue: 256}} | ||
bottomLeft={{red: 0, green: 256, blue: 256}} | ||
bottomRight={{red: 256, green: 256, blue: 256}} | ||
steps={64} /* the larger the number the worse performance */ | ||
/> | ||
</ColorPickerContext.Provider> | ||
current color = {color ? toCssColor(color) : "none"} | ||
</div> | ||
); | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import {ReactElement} from "react"; | ||
|
||
import {Swatch} from "./swatch"; | ||
import {Color, lerpColor} from "../../shared/color"; | ||
|
||
type Props = { | ||
start: Color; | ||
stop: Color; | ||
steps: number; | ||
}; | ||
|
||
export function Gradient({start, stop, steps}: Props) { | ||
const swatches: Array<ReactElement<typeof Swatch>> = []; | ||
for (let i = 0; i < steps; i++) { | ||
const color = lerpColor(start, stop, i / steps); | ||
swatches.push(<Swatch color={color} size={512 / steps} />); | ||
} | ||
|
||
return ( | ||
<div style={{display: "flex", flexDirection: "row"}}>{swatches}</div> | ||
); | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import {ReactElement} from "react"; | ||
|
||
import {Gradient} from "./gradient"; | ||
import {Color, lerpColor} from "../../shared/color"; | ||
|
||
type Props = { | ||
topLeft: Color; | ||
topRight: Color; | ||
bottomLeft: Color; | ||
bottomRight: Color; | ||
steps: number; | ||
}; | ||
|
||
export function Grid({ | ||
topLeft, | ||
topRight, | ||
bottomLeft, | ||
bottomRight, | ||
steps, | ||
}: Props) { | ||
const gradients: Array<ReactElement<typeof Gradient>> = []; | ||
for (let i = 0; i < steps; i++) { | ||
const start = lerpColor(topLeft, bottomLeft, i / steps); | ||
const stop = lerpColor(topRight, bottomRight, i / steps); | ||
gradients.push(<Gradient start={start} stop={stop} steps={steps} />); | ||
} | ||
|
||
return ( | ||
<div style={{display: "flex", flexDirection: "column"}}> | ||
{gradients} | ||
</div> | ||
); | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,10 @@ | ||
import {ColorPicker} from "./color-picker"; | ||
|
||
export default function Exercise2() { | ||
return <h1>Exercise 2: Prevent Context From Rendering</h1>; | ||
return ( | ||
<div> | ||
<h1>Solution 2: Prevent Context From Rendering</h1> | ||
<ColorPicker /> | ||
</div> | ||
); | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import {useContext} from "react"; | ||
|
||
import {Color, toCssColor} from "../../shared/color"; | ||
import {ColorPickerContext} from "./color-picker-context"; | ||
|
||
type Props = { | ||
color: Color; | ||
size: number; | ||
}; | ||
|
||
export function Swatch({color, size}: Props) { | ||
const {setColor, color: selectedColor} = useContext(ColorPickerContext)!; | ||
|
||
const isSelected = | ||
selectedColor && | ||
selectedColor.red === color.red && | ||
selectedColor.green === color.green && | ||
selectedColor.blue === color.blue; | ||
|
||
return ( | ||
<div | ||
style={{ | ||
width: size, | ||
height: size, | ||
background: toCssColor(color), | ||
boxSizing: "border-box", | ||
border: isSelected ? "1px solid black" : "none", | ||
}} | ||
onClick={() => setColor(color)} | ||
/> | ||
); | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import {fib} from "../../shared/fib"; | ||
import {Circle} from "../../shared/shapes"; | ||
|
||
type Props = { | ||
circle: Circle; | ||
onClick: () => void; | ||
}; | ||
|
||
export function ChildComponent({circle, onClick}: Props) { | ||
return ( | ||
<div> | ||
<h1>Child Component</h1> | ||
<p>fib(36) = {fib(36)}</p> | ||
<button onClick={onClick}>Click me!</button> | ||
<svg> | ||
<circle | ||
r={circle.radius} | ||
cx={circle.center.x} | ||
cy={circle.center.y} | ||
/> | ||
</svg> | ||
</div> | ||
); | ||
} |
10 changes: 10 additions & 0 deletions
10
src/react-render-perf/lesson-02/solution/color-picker-context.tsx
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import {createContext} from "react"; | ||
|
||
import { | ||
colorPickerEventEmitter, | ||
ColorPickerEventEmitter, | ||
} from "./color-picker-event-emitter"; | ||
|
||
export const ColorPickerContext = createContext<ColorPickerEventEmitter>( | ||
colorPickerEventEmitter, | ||
); |
24 changes: 24 additions & 0 deletions
24
src/react-render-perf/lesson-02/solution/color-picker-event-emitter.ts
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import {EventEmitter} from "eventemitter3"; | ||
|
||
export class ColorPickerEventEmitter extends EventEmitter { | ||
selectedColor: string | undefined; | ||
|
||
public onColorChange(color: string, callback: (state: boolean) => void) { | ||
this.on(color, callback); | ||
} | ||
|
||
public onSelectedColorChange(callback: (selectedColor: string) => void) { | ||
this.on("any", callback); | ||
} | ||
|
||
public selectColor(color: string) { | ||
if (this.selectedColor && this.selectedColor !== color) { | ||
this.emit(this.selectedColor, false); | ||
} | ||
this.emit(color, true); | ||
this.emit("any", color); | ||
this.selectedColor = color; | ||
} | ||
} | ||
|
||
export const colorPickerEventEmitter = new ColorPickerEventEmitter(); |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import {useContext, useState} from "react"; | ||
|
||
import Grid from "./grid"; | ||
import {ColorPickerContext} from "./color-picker-context"; | ||
|
||
export function ColorPicker() { | ||
const [color, setColor] = useState<string | undefined>(undefined); | ||
const colorPickerEventEmitter = useContext(ColorPickerContext)!; | ||
colorPickerEventEmitter.onSelectedColorChange(setColor); | ||
|
||
return ( | ||
<div> | ||
<Grid | ||
topLeft={{red: 0, green: 0, blue: 256}} | ||
topRight={{red: 256, green: 0, blue: 256}} | ||
bottomLeft={{red: 0, green: 256, blue: 256}} | ||
bottomRight={{red: 256, green: 256, blue: 256}} | ||
steps={64} /* the larger the number the worse performance */ | ||
/> | ||
current color = {color ? color : "none"} | ||
</div> | ||
); | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import {ReactElement} from "react"; | ||
|
||
import {Swatch} from "./swatch"; | ||
import {Color, lerpColor, toCssColor} from "../../shared/color"; | ||
|
||
type Props = { | ||
start: Color; | ||
stop: Color; | ||
steps: number; | ||
}; | ||
|
||
export function Gradient({start, stop, steps}: Props) { | ||
const swatches: Array<ReactElement<typeof Swatch>> = []; | ||
for (let i = 0; i < steps; i++) { | ||
const color = lerpColor(start, stop, i / steps); | ||
swatches.push( | ||
<Swatch key={toCssColor(color)} color={color} size={512 / steps} />, | ||
); | ||
} | ||
|
||
return ( | ||
<div style={{display: "flex", flexDirection: "row"}}>{swatches}</div> | ||
); | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
import {ReactElement, memo} from "react"; | ||
import arePropsEqual from "react-fast-compare"; | ||
|
||
import {Gradient} from "./gradient"; | ||
import {Color, lerpColor, toCssColor} from "../../shared/color"; | ||
|
||
type Props = { | ||
topLeft: Color; | ||
topRight: Color; | ||
bottomLeft: Color; | ||
bottomRight: Color; | ||
steps: number; | ||
}; | ||
|
||
export default memo(function Grid({ | ||
topLeft, | ||
topRight, | ||
bottomLeft, | ||
bottomRight, | ||
steps, | ||
}: Props) { | ||
const gradients: Array<ReactElement<typeof Gradient>> = []; | ||
for (let i = 0; i < steps; i++) { | ||
const start = lerpColor(topLeft, bottomLeft, i / steps); | ||
const stop = lerpColor(topRight, bottomRight, i / steps); | ||
const key = `${toCssColor(start)}-${toCssColor(stop)}`; | ||
gradients.push( | ||
<Gradient key={key} start={start} stop={stop} steps={steps} />, | ||
); | ||
} | ||
|
||
return ( | ||
<div style={{display: "flex", flexDirection: "column"}}> | ||
{gradients} | ||
</div> | ||
); | ||
}, arePropsEqual); |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import {ColorPicker} from "./color-picker"; | ||
|
||
export default function Exercise2() { | ||
return ( | ||
<div> | ||
<h1>Solution 2: Prevent Context From Rendering</h1> | ||
<ColorPicker /> | ||
</div> | ||
); | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,10 @@ | ||
import {ColorPicker} from "./color-picker"; | ||
|
||
export default function Solution2() { | ||
return <h1>Solution 2: Prevent Context From Rendering</h1>; | ||
return ( | ||
<div> | ||
<h1>Solution 2: Prevent Context From Rendering</h1> | ||
<ColorPicker /> | ||
</div> | ||
); | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import {useContext, useState} from "react"; | ||
|
||
import {Color, toCssColor} from "../../shared/color"; | ||
import {ColorPickerContext} from "./color-picker-context"; | ||
|
||
type Props = { | ||
color: Color; | ||
size: number; | ||
}; | ||
|
||
export function Swatch({color, size}: Props) { | ||
const colorPickerEventEmitter = useContext(ColorPickerContext)!; | ||
const [isSelected, setIsSelected] = useState(false); | ||
|
||
colorPickerEventEmitter.onColorChange(toCssColor(color), setIsSelected); | ||
|
||
return ( | ||
<div | ||
style={{ | ||
width: size, | ||
height: size, | ||
background: toCssColor(color), | ||
boxSizing: "border-box", | ||
border: isSelected ? "1px solid black" : "none", | ||
}} | ||
onClick={() => | ||
colorPickerEventEmitter.selectColor(toCssColor(color)) | ||
} | ||
/> | ||
); | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
export type Color = { | ||
red: number; | ||
green: number; | ||
blue: number; | ||
}; | ||
|
||
export function toCssColor(color: Color) { | ||
return `rgb(${color.red}, ${color.green}, ${color.blue})`; | ||
} | ||
|
||
export function lerpColor(start: Color, end: Color, t: number): Color { | ||
return { | ||
red: lerp(start.red, end.red, t), | ||
green: lerp(start.green, end.green, t), | ||
blue: lerp(start.blue, end.blue, t), | ||
}; | ||
} | ||
|
||
function lerp(start: number, end: number, t: number) { | ||
return start + (end - start) * t; | ||
} |
Oops, something went wrong.