Skip to content

Commit afc6af0

Browse files
authored
Update main.jsx
1 parent c359d3b commit afc6af0

File tree

1 file changed

+94
-250
lines changed

1 file changed

+94
-250
lines changed
Lines changed: 94 additions & 250 deletions
Original file line numberDiff line numberDiff line change
@@ -1,63 +1,15 @@
1-
import React, { Component } from "react";
2-
import { createRoot } from "react-dom";
1+
import React from 'react';
2+
import { memo, useReducer } from 'react';
3+
import { createRoot } from 'react-dom';
34

45
const random = (max) => Math.round(Math.random() * 1000) % max;
56

6-
const A = [
7-
"pretty",
8-
"large",
9-
"big",
10-
"small",
11-
"tall",
12-
"short",
13-
"long",
14-
"handsome",
15-
"plain",
16-
"quaint",
17-
"clean",
18-
"elegant",
19-
"easy",
20-
"angry",
21-
"crazy",
22-
"helpful",
23-
"mushy",
24-
"odd",
25-
"unsightly",
26-
"adorable",
27-
"important",
28-
"inexpensive",
29-
"cheap",
30-
"expensive",
31-
"fancy",
32-
];
33-
const C = [
34-
"red",
35-
"yellow",
36-
"blue",
37-
"green",
38-
"pink",
39-
"brown",
40-
"purple",
41-
"brown",
42-
"white",
43-
"black",
44-
"orange",
45-
];
46-
const N = [
47-
"table",
48-
"chair",
49-
"house",
50-
"bbq",
51-
"desk",
52-
"car",
53-
"pony",
54-
"cookie",
55-
"sandwich",
56-
"burger",
57-
"pizza",
58-
"mouse",
59-
"keyboard",
60-
];
7+
const A = ["pretty", "large", "big", "small", "tall", "short", "long", "handsome", "plain", "quaint", "clean",
8+
"elegant", "easy", "angry", "crazy", "helpful", "mushy", "odd", "unsightly", "adorable", "important", "inexpensive",
9+
"cheap", "expensive", "fancy"];
10+
const C = ["red", "yellow", "blue", "green", "pink", "brown", "purple", "brown", "white", "black", "orange"];
11+
const N = ["table", "chair", "house", "bbq", "desk", "car", "pony", "cookie", "sandwich", "burger", "pizza", "mouse",
12+
"keyboard"];
6113

6214
let nextId = 1;
6315

@@ -67,9 +19,7 @@ const buildData = (count) => {
6719
for (let i = 0; i < count; i++) {
6820
data[i] = {
6921
id: nextId++,
70-
label: `${A[random(A.length)]} ${C[random(C.length)]} ${
71-
N[random(N.length)]
72-
}`,
22+
label: `${A[random(A.length)]} ${C[random(C.length)]} ${N[random(N.length)]}`,
7323
};
7424
}
7525

@@ -78,204 +28,98 @@ const buildData = (count) => {
7828

7929
const initialState = { data: [], selected: 0 };
8030

81-
class Row extends Component {
82-
shouldComponentUpdate(nextProps) {
83-
const { item, selected } = this.props;
31+
const listReducer = (state, action) => {
32+
const { data, selected } = state;
8433

85-
return nextProps.item !== item || nextProps.selected !== selected;
86-
}
87-
88-
constructor(props) {
89-
super(props);
90-
91-
this.onSelect = () => {
92-
const { item, dispatch } = this.props;
93-
94-
dispatch({ type: "SELECT", id: item.id });
95-
};
96-
97-
this.onRemove = () => {
98-
const { item, dispatch } = this.props;
99-
100-
dispatch({ type: "REMOVE", id: item.id });
101-
};
102-
}
103-
104-
render() {
105-
const { selected, item } = this.props;
34+
switch (action.type) {
35+
case 'RUN':
36+
return { data: buildData(1000), selected: 0 };
37+
case 'RUN_LOTS':
38+
return { data: buildData(10000), selected: 0 };
39+
case 'ADD':
40+
return { data: data.concat(buildData(1000)), selected };
41+
case 'UPDATE': {
42+
const newData = data.slice(0);
10643

107-
return (
108-
<tr className={selected ? "danger" : ""}>
109-
<td className="col-md-1">{item.id}</td>
110-
<td className="col-md-4">
111-
<a onClick={this.onSelect}>{item.label}</a>
112-
</td>
113-
<td className="col-md-1">
114-
<a onClick={this.onRemove}>
115-
<span className="glyphicon glyphicon-remove" aria-hidden="true" />
116-
</a>
117-
</td>
118-
<td className="col-md-6" />
119-
</tr>
120-
);
121-
}
122-
}
123-
124-
class Button extends Component {
125-
render() {
126-
const { id, cb, title } = this.props;
44+
for (let i = 0; i < newData.length; i += 10) {
45+
const r = newData[i];
12746

128-
return (
129-
<div className="col-sm-6 smallpad">
130-
<button
131-
type="button"
132-
className="btn btn-primary btn-block"
133-
id={id}
134-
onClick={cb}
135-
>
136-
{title}
137-
</button>
138-
</div>
139-
);
140-
}
141-
}
47+
newData[i] = { id: r.id, label: r.label + " !!!" };
48+
}
14249

143-
class Jumbotron extends Component {
144-
shouldComponentUpdate() {
145-
return false;
50+
return { data: newData, selected };
51+
}
52+
case 'CLEAR':
53+
return { data: [], selected: 0 };
54+
case 'SWAP_ROWS':
55+
return data.length > 998 ? { data: [data[0], data[998], ...data.slice(2, 998), data[1], data[999]], selected } : state;
56+
case 'REMOVE': {
57+
const idx = data.findIndex((d) => d.id === action.id);
58+
59+
return { data: [...data.slice(0, idx), ...data.slice(idx + 1)], selected };
60+
}
61+
case 'SELECT':
62+
return { data, selected: action.id };
63+
default:
64+
return state;
14665
}
66+
};
14767

148-
render() {
149-
const { dispatch } = this.props;
150-
151-
return (
152-
<div className="jumbotron">
153-
<div className="row">
154-
<div className="col-md-6">
155-
<h1>React Lab keyed</h1>
156-
</div>
157-
<div className="col-md-6">
158-
<div className="row">
159-
<Button
160-
id="run"
161-
title="Create 1,000 rows"
162-
cb={() => dispatch({ type: "RUN" })}
163-
/>
164-
<Button
165-
id="runlots"
166-
title="Create 10,000 rows"
167-
cb={() => dispatch({ type: "RUN_LOTS" })}
168-
/>
169-
<Button
170-
id="add"
171-
title="Append 1,000 rows"
172-
cb={() => dispatch({ type: "ADD" })}
173-
/>
174-
<Button
175-
id="update"
176-
title="Update every 10th row"
177-
cb={() => dispatch({ type: "UPDATE" })}
178-
/>
179-
<Button
180-
id="clear"
181-
title="Clear"
182-
cb={() => dispatch({ type: "CLEAR" })}
183-
/>
184-
<Button
185-
id="swaprows"
186-
title="Swap Rows"
187-
cb={() => dispatch({ type: "SWAP_ROWS" })}
188-
/>
189-
</div>
68+
const Row = memo(({ selected, item, dispatch }) => (
69+
<tr className={selected ? "danger" : ""}>
70+
<td className="col-md-1">{item.id}</td>
71+
<td className="col-md-4">
72+
<a onClick={() => dispatch({ type: 'SELECT', id: item.id })}>{item.label}</a>
73+
</td>
74+
<td className="col-md-1">
75+
<a onClick={() => dispatch({ type: 'REMOVE', id: item.id })}>
76+
<span className="glyphicon glyphicon-remove" aria-hidden="true" />
77+
</a>
78+
</td>
79+
<td className="col-md-6" />
80+
</tr>
81+
), (prevProps, nextProps) => prevProps.selected === nextProps.selected && prevProps.item === nextProps.item)
82+
83+
const Button = ({ id, cb, title }) => (
84+
<div className="col-sm-6 smallpad">
85+
<button type="button" className="btn btn-primary btn-block" id={id} onClick={cb}>{title}</button>
86+
</div>
87+
);
88+
89+
const Jumbotron = memo(({ dispatch }) => (
90+
<div className="jumbotron">
91+
<div className="row">
92+
<div className="col-md-6">
93+
<h1>React Lab Hooks keyed</h1>
94+
</div>
95+
<div className="col-md-6">
96+
<div className="row">
97+
<Button id="run" title="Create 1,000 rows" cb={() => dispatch({ type: 'RUN' })} />
98+
<Button id="runlots" title="Create 10,000 rows" cb={() => dispatch({ type: 'RUN_LOTS' })} />
99+
<Button id="add" title="Append 1,000 rows" cb={() => dispatch({ type: 'ADD' })} />
100+
<Button id="update" title="Update every 10th row" cb={() => dispatch({ type: 'UPDATE' })} />
101+
<Button id="clear" title="Clear" cb={() => dispatch({ type: 'CLEAR' })} />
102+
<Button id="swaprows" title="Swap Rows" cb={() => dispatch({ type: 'SWAP_ROWS' })} />
190103
</div>
191104
</div>
192105
</div>
193-
);
194-
}
195-
}
196-
197-
class Main extends Component {
198-
constructor(props) {
199-
super(props);
200-
201-
this.state = initialState;
202-
203-
this.dispatch = (action) => {
204-
const { data } = this.state;
205-
206-
switch (action.type) {
207-
case "RUN":
208-
return this.setState({ data: buildData(1000), selected: 0 });
209-
case "RUN_LOTS":
210-
return this.setState({ data: buildData(10000), selected: 0 });
211-
case "ADD":
212-
return this.setState({ data: data.concat(buildData(1000)) });
213-
case "UPDATE": {
214-
const newData = data.slice(0);
215-
216-
for (let i = 0; i < newData.length; i += 10) {
217-
const r = newData[i];
218-
219-
newData[i] = { id: r.id, label: r.label + " !!!" };
220-
}
221-
222-
return this.setState({ data: newData });
223-
}
224-
case "CLEAR":
225-
return this.setState({ data: [], selected: 0 });
226-
case "SWAP_ROWS": {
227-
if (data.length > 998) {
228-
return this.setState({
229-
data: [
230-
data[0],
231-
data[998],
232-
...data.slice(2, 998),
233-
data[1],
234-
data[999],
235-
],
236-
});
237-
}
238-
239-
return;
240-
}
241-
case "REMOVE": {
242-
const idx = data.findIndex((d) => d.id === action.id);
243-
244-
return this.setState({
245-
data: [...data.slice(0, idx), ...data.slice(idx + 1)],
246-
});
247-
}
248-
case "SELECT":
249-
return this.setState({ selected: action.id });
250-
}
251-
};
252-
}
253-
254-
render() {
255-
const { data, selected } = this.state;
256-
257-
return (
258-
<div className="container">
259-
<Jumbotron dispatch={this.dispatch} />
260-
<table className="table table-hover table-striped test-data">
261-
<tbody>
262-
{data.map((item) => (
263-
<Row
264-
key={item.id}
265-
item={item}
266-
selected={selected === item.id}
267-
dispatch={this.dispatch}
268-
/>
269-
))}
270-
</tbody>
271-
</table>
272-
<span
273-
className="preloadicon glyphicon glyphicon-remove"
274-
aria-hidden="true"
275-
/>
276-
</div>
277-
);
278-
}
106+
</div>
107+
), () => true);
108+
109+
const Main = () => {
110+
const [{ data, selected }, dispatch] = useReducer(listReducer, initialState);
111+
112+
return (<div className="container">
113+
<Jumbotron dispatch={dispatch} />
114+
<table className="table table-hover table-striped test-data">
115+
<tbody>
116+
{data.map(item => (
117+
<Row key={item.id} item={item} selected={selected === item.id} dispatch={dispatch} />
118+
))}
119+
</tbody>
120+
</table>
121+
<span className="preloadicon glyphicon glyphicon-remove" aria-hidden="true" />
122+
</div>);
279123
}
280124

281-
createRoot(document.getElementById("main")).render(<Main />);
125+
createRoot(document.getElementById("main")).render(<Main/>);

0 commit comments

Comments
 (0)