-
Notifications
You must be signed in to change notification settings - Fork 2k
/
Container.tsx
108 lines (90 loc) · 2.18 KB
/
Container.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
import Faker from 'faker'
import update from 'immutability-helper'
import type { CSSProperties } from 'react'
import { Component } from 'react'
import { Card } from './Card.js'
const style: CSSProperties = {
width: 400,
}
interface CardItem {
id: number
text: string
}
export interface CardState {
cardsById: Record<string, CardItem>
cardsByIndex: CardItem[]
}
function buildCardData() {
const cardsById: Record<string, CardItem> = {}
const cardsByIndex: CardItem[] = []
for (let i = 0; i < 1000; i += 1) {
const card = { id: i, text: Faker.name.findName() }
cardsById[card.id] = card
cardsByIndex[i] = card
}
return {
cardsById,
cardsByIndex,
}
}
/* eslint-disable-next-line @typescript-eslint/no-empty-interface */
export interface ContainerProps {}
export class Container extends Component<
ContainerProps,
Record<string, unknown>
> {
private requestedFrame: number | undefined
private cardState: CardState = buildCardData()
public constructor(props: ContainerProps) {
super(props)
this.state = STATE
}
public override componentWillUnmount(): void {
if (this.requestedFrame !== undefined) {
cancelAnimationFrame(this.requestedFrame)
}
}
public override render(): JSX.Element {
const { cardsByIndex } = this.cardState
return (
<>
<div style={style}>
{cardsByIndex.map((card) => (
<Card
key={card.id}
id={card.id}
text={card.text}
moveCard={this.moveCard}
/>
))}
</div>
</>
)
}
private moveCard = (id: string, afterId: string): void => {
const { cardsById, cardsByIndex } = this.cardState
const card = cardsById[id] as CardItem
const afterCard = cardsById[afterId] as CardItem
const cardIndex = cardsByIndex.indexOf(card)
const afterIndex = cardsByIndex.indexOf(afterCard)
this.cardState = update(this.cardState, {
cardsByIndex: {
$splice: [
[cardIndex, 1],
[afterIndex, 0, card],
],
},
})
this.scheduleUpdate()
}
private scheduleUpdate() {
if (!this.requestedFrame) {
this.requestedFrame = requestAnimationFrame(this.drawFrame)
}
}
private drawFrame = (): void => {
this.setState(STATE)
this.requestedFrame = undefined
}
}
const STATE = {}