feat: auth & admin
This commit is contained in:
@@ -10,55 +10,60 @@ tags: javascript, dom, css, performance, reflow, layout-thrashing
|
||||
Avoid interleaving style writes with layout reads. When you read a layout property (like `offsetWidth`, `getBoundingClientRect()`, or `getComputedStyle()`) between style changes, the browser is forced to trigger a synchronous reflow.
|
||||
|
||||
**This is OK (browser batches style changes):**
|
||||
|
||||
```typescript
|
||||
function updateElementStyles(element: HTMLElement) {
|
||||
// Each line invalidates style, but browser batches the recalculation
|
||||
element.style.width = '100px'
|
||||
element.style.height = '200px'
|
||||
element.style.backgroundColor = 'blue'
|
||||
element.style.border = '1px solid black'
|
||||
element.style.width = '100px';
|
||||
element.style.height = '200px';
|
||||
element.style.backgroundColor = 'blue';
|
||||
element.style.border = '1px solid black';
|
||||
}
|
||||
```
|
||||
|
||||
**Incorrect (interleaved reads and writes force reflows):**
|
||||
|
||||
```typescript
|
||||
function layoutThrashing(element: HTMLElement) {
|
||||
element.style.width = '100px'
|
||||
const width = element.offsetWidth // Forces reflow
|
||||
element.style.height = '200px'
|
||||
const height = element.offsetHeight // Forces another reflow
|
||||
element.style.width = '100px';
|
||||
const width = element.offsetWidth; // Forces reflow
|
||||
element.style.height = '200px';
|
||||
const height = element.offsetHeight; // Forces another reflow
|
||||
}
|
||||
```
|
||||
|
||||
**Correct (batch writes, then read once):**
|
||||
|
||||
```typescript
|
||||
function updateElementStyles(element: HTMLElement) {
|
||||
// Batch all writes together
|
||||
element.style.width = '100px'
|
||||
element.style.height = '200px'
|
||||
element.style.backgroundColor = 'blue'
|
||||
element.style.border = '1px solid black'
|
||||
|
||||
element.style.width = '100px';
|
||||
element.style.height = '200px';
|
||||
element.style.backgroundColor = 'blue';
|
||||
element.style.border = '1px solid black';
|
||||
|
||||
// Read after all writes are done (single reflow)
|
||||
const { width, height } = element.getBoundingClientRect()
|
||||
const { width, height } = element.getBoundingClientRect();
|
||||
}
|
||||
```
|
||||
|
||||
**Correct (batch reads, then writes):**
|
||||
|
||||
```typescript
|
||||
function avoidThrashing(element: HTMLElement) {
|
||||
// Read phase - all layout queries first
|
||||
const rect1 = element.getBoundingClientRect()
|
||||
const offsetWidth = element.offsetWidth
|
||||
const offsetHeight = element.offsetHeight
|
||||
|
||||
const rect1 = element.getBoundingClientRect();
|
||||
const offsetWidth = element.offsetWidth;
|
||||
const offsetHeight = element.offsetHeight;
|
||||
|
||||
// Write phase - all style changes after
|
||||
element.style.width = '100px'
|
||||
element.style.height = '200px'
|
||||
element.style.width = '100px';
|
||||
element.style.height = '200px';
|
||||
}
|
||||
```
|
||||
|
||||
**Better: use CSS classes**
|
||||
|
||||
```css
|
||||
.highlighted-box {
|
||||
width: 100px;
|
||||
@@ -67,38 +72,36 @@ function avoidThrashing(element: HTMLElement) {
|
||||
border: 1px solid black;
|
||||
}
|
||||
```
|
||||
|
||||
```typescript
|
||||
function updateElementStyles(element: HTMLElement) {
|
||||
element.classList.add('highlighted-box')
|
||||
|
||||
const { width, height } = element.getBoundingClientRect()
|
||||
element.classList.add('highlighted-box');
|
||||
|
||||
const { width, height } = element.getBoundingClientRect();
|
||||
}
|
||||
```
|
||||
|
||||
**React example:**
|
||||
|
||||
```tsx
|
||||
// Incorrect: interleaving style changes with layout queries
|
||||
function Box({ isHighlighted }: { isHighlighted: boolean }) {
|
||||
const ref = useRef<HTMLDivElement>(null)
|
||||
|
||||
const ref = useRef<HTMLDivElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (ref.current && isHighlighted) {
|
||||
ref.current.style.width = '100px'
|
||||
const width = ref.current.offsetWidth // Forces layout
|
||||
ref.current.style.height = '200px'
|
||||
ref.current.style.width = '100px';
|
||||
const width = ref.current.offsetWidth; // Forces layout
|
||||
ref.current.style.height = '200px';
|
||||
}
|
||||
}, [isHighlighted])
|
||||
|
||||
return <div ref={ref}>Content</div>
|
||||
}, [isHighlighted]);
|
||||
|
||||
return <div ref={ref}>Content</div>;
|
||||
}
|
||||
|
||||
// Correct: toggle class
|
||||
function Box({ isHighlighted }: { isHighlighted: boolean }) {
|
||||
return (
|
||||
<div className={isHighlighted ? 'highlighted-box' : ''}>
|
||||
Content
|
||||
</div>
|
||||
)
|
||||
return <div className={isHighlighted ? 'highlighted-box' : ''}>Content</div>;
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
Reference in New Issue
Block a user