Skip to content

Commit bbf4c88

Browse files
committed
2 parents 045e906 + 838322a commit bbf4c88

File tree

7 files changed

+2579
-412
lines changed

7 files changed

+2579
-412
lines changed

frameworks/keyed/jotai/.babelrc

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"presets": [
3+
[
4+
"@babel/preset-env",
5+
{
6+
"targets": {
7+
"browsers": ["last 1 chrome versions"]
8+
}
9+
}
10+
],
11+
"@babel/preset-typescript",
12+
"@babel/preset-react"
13+
]
14+
}

frameworks/keyed/jotai/package-lock.json

+2,460-244
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

frameworks/keyed/jotai/package.json

+11-11
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
"frameworkVersionFromPackage": "react:jotai"
88
},
99
"scripts": {
10-
"build-dev": "rollup -c -w",
11-
"build-prod": "rollup -c"
10+
"build-dev": "webpack --watch",
11+
"build-prod": "webpack"
1212
},
1313
"keywords": [
1414
"react",
@@ -24,18 +24,18 @@
2424
"dependencies": {
2525
"react": "17.0.1",
2626
"react-dom": "17.0.1",
27-
"jotai": "0.16.8"
27+
"jotai": "1.0.0"
2828
},
2929
"devDependencies": {
30-
"@rollup/plugin-commonjs": "^17.1.0",
31-
"@rollup/plugin-node-resolve": "^11.2.0",
32-
"@rollup/plugin-replace": "^2.4.1",
33-
"@rollup/plugin-typescript": "^8.2.0",
30+
"@babel/core": "^7.14.5",
31+
"@babel/preset-env": "^7.14.5",
32+
"@babel/preset-react": "^7.14.5",
33+
"@babel/preset-typescript": "^7.14.5",
3434
"@types/react": "17.0.2",
3535
"@types/react-dom": "17.0.1",
36-
"rollup": "^2.40.0",
37-
"rollup-plugin-terser": "^7.0.2",
38-
"tslib": "^2.1.0",
39-
"typescript": "4.2.2"
36+
"babel-loader": "^8.2.2",
37+
"typescript": "4.2.2",
38+
"webpack": "^5.39.0",
39+
"webpack-cli": "^4.7.2"
4040
}
4141
}

frameworks/keyed/jotai/rollup.config.js

-22
This file was deleted.

frameworks/keyed/jotai/src/main.tsx

+51-72
Original file line numberDiff line numberDiff line change
@@ -1,111 +1,91 @@
1-
import { memo, FC } from "react";
1+
import React, { memo, FC } from "react";
22
import ReactDOM from "react-dom";
3-
import { atom, useAtom } from "jotai";
3+
import { atom, useAtom, PrimitiveAtom } from "jotai";
44
import { useUpdateAtom } from "jotai/utils";
55

6-
import { buildData, Data } from "./utils";
6+
import { Data, buildDataAtoms } from "./utils";
77

8-
const stateAtom = atom<{ data: Data[]; selected: number }>({
9-
data: [],
10-
selected: 0,
11-
});
8+
const dataAtom = atom<PrimitiveAtom<Data>[]>([]);
9+
const selectedAtom = atom<PrimitiveAtom<Data> | null>(null);
1210

13-
const createRowsAtom = atom(null, (_, set, amount: number) =>
14-
set(stateAtom, { data: buildData(amount), selected: 0 })
15-
);
11+
const createRowsAtom = atom(null, (_, set, amount: number) => {
12+
set(dataAtom, buildDataAtoms(amount));
13+
set(selectedAtom, null);
14+
});
1615

17-
const appendRowsAtom = atom(null, (_, set) =>
18-
set(stateAtom, (state) => ({
19-
data: state.data.concat(buildData(1000)),
20-
selected: 0,
21-
}))
22-
);
16+
const appendRowsAtom = atom(null, (_, set) => {
17+
set(dataAtom, (data) => data.concat(buildDataAtoms(1000)));
18+
set(selectedAtom, null);
19+
});
2320

24-
const updateRowsAtom = atom(null, (_, set) =>
25-
set(stateAtom, ({ data, selected }) => {
26-
const newData = data.slice(0);
27-
for (let i = 0; i < newData.length; i += 10) {
28-
const r = newData[i];
29-
newData[i] = { id: r.id, label: r.label + " !!!" };
30-
}
31-
return { data: newData, selected };
32-
})
33-
);
21+
const updateRowsAtom = atom(null, (get, set) => {
22+
const data = get(dataAtom);
23+
for (let i = 0; i < data.length; i += 10) {
24+
set(data[i], (r) => ({ id: r.id, label: r.label + " !!!" }));
25+
}
26+
});
3427

35-
const removeRowAtom = atom(null, (_, set, id: number) =>
36-
set(stateAtom, ({ data, selected }) => {
37-
const idx = data.findIndex((d) => d.id === id);
38-
return { data: [...data.slice(0, idx), ...data.slice(idx + 1)], selected };
28+
const removeRowAtom = atom(null, (_, set, item: PrimitiveAtom<Data>) =>
29+
set(dataAtom, (data) => {
30+
const idx = data.findIndex((d) => d === item);
31+
return [...data.slice(0, idx), ...data.slice(idx + 1)];
3932
})
4033
);
4134

42-
const selectRowAtom = atom(null, (_, set, selected: number) =>
43-
set(stateAtom, (state) => ({ data: state.data, selected }))
44-
);
35+
const selectRowAtom = atom(null, (_, set, selected: PrimitiveAtom<Data>) => {
36+
set(selectedAtom, selected);
37+
});
4538

46-
const clearStateAtom = atom(null, (_, set) =>
47-
set(stateAtom, () => ({
48-
data: [],
49-
selected: 0,
50-
}))
51-
);
39+
const clearStateAtom = atom(null, (_, set) => {
40+
set(dataAtom, []);
41+
set(selectedAtom, null);
42+
});
5243

53-
const swapRowsAtom = atom(null, (_, set) =>
54-
set(stateAtom, (state) => {
55-
const { data, selected } = state;
56-
return data.length > 998
57-
? {
58-
data: [data[0], data[998], ...data.slice(2, 998), data[1], data[999]],
59-
selected,
60-
}
61-
: state;
62-
})
63-
);
44+
const swapRowsAtom = atom(null, (get, set) => {
45+
const data = get(dataAtom);
46+
if (data.length > 998) {
47+
set(dataAtom, [data[0], data[998], ...data.slice(2, 998), data[1], data[999]])
48+
}
49+
});
6450

6551
const GlyphIcon = (
6652
<span className="glyphicon glyphicon-remove" aria-hidden="true"></span>
6753
);
6854

6955
interface RowProps {
70-
id: number;
71-
label: string;
56+
item: PrimitiveAtom<Data>;
7257
isSelected: boolean;
73-
selectRow: (id: number) => void;
74-
removeRow: (id: number) => void;
7558
}
7659

77-
const Row = memo<RowProps>(({ id, label, isSelected, selectRow, removeRow }) => {
60+
const Row = memo<RowProps>(({ item, isSelected }) => {
61+
const [{ id, label }] = useAtom(item);
62+
const selectRow = useUpdateAtom(selectRowAtom);
63+
const removeRow = useUpdateAtom(removeRowAtom);
7864
return (
7965
<tr className={isSelected ? "danger" : ""}>
8066
<td className="col-md-1">{id}</td>
8167
<td className="col-md-4">
82-
<a onClick={() => selectRow(id)}>{label}</a>
68+
<a onClick={() => selectRow(item)}>{label}</a>
8369
</td>
8470
<td className="col-md-1">
85-
<a onClick={() => removeRow(id)}>{GlyphIcon}</a>
71+
<a onClick={() => removeRow(item)}>{GlyphIcon}</a>
8672
</td>
8773
<td className="col-md-6"></td>
8874
</tr>
8975
);
9076
});
9177

92-
interface RowListProp {
93-
selectRow: (id: number) => void;
94-
removeRow: (id: number) => void;
95-
}
9678

97-
const RowList = memo<RowListProp>(({ selectRow, removeRow }) => {
98-
const [{ data, selected }] = useAtom(stateAtom);
79+
const RowList = memo(() => {
80+
const [data] = useAtom(dataAtom);
81+
const [selected] = useAtom(selectedAtom);
9982
return (
10083
<>
10184
{data.map((item) => (
10285
<Row
103-
key={item.id}
104-
id={item.id}
105-
label={item.label}
106-
isSelected={selected === item.id}
107-
selectRow={selectRow}
108-
removeRow={removeRow}
86+
key={String(item)}
87+
item={item}
88+
isSelected={item === selected}
10989
/>
11090
))}
11191
</>
@@ -137,8 +117,7 @@ const Main: FC = () => {
137117
const updateRows = useUpdateAtom(updateRowsAtom);
138118
const clearState = useUpdateAtom(clearStateAtom);
139119
const swapRows = useUpdateAtom(swapRowsAtom);
140-
const selectRow = useUpdateAtom(selectRowAtom);
141-
const removeRow = useUpdateAtom(removeRowAtom);
120+
142121
return (
143122
<div className="container">
144123
<div className="jumbotron">
@@ -172,7 +151,7 @@ const Main: FC = () => {
172151
</div>
173152
<table className="table table-hover table-striped test-data">
174153
<tbody>
175-
<RowList selectRow={selectRow} removeRow={removeRow} />
154+
<RowList />
176155
</tbody>
177156
</table>
178157
<span

frameworks/keyed/jotai/src/utils.ts

+13-63
Original file line numberDiff line numberDiff line change
@@ -1,62 +1,12 @@
1-
export function random(max: number) {
1+
import { atom, PrimitiveAtom } from "jotai";
2+
3+
function random(max: number) {
24
return Math.round(Math.random() * 1000) % max;
35
}
46

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

6111
let nextId = 1;
6212

@@ -65,15 +15,15 @@ export interface Data {
6515
label: string;
6616
}
6717

68-
export function buildData(count: number): Data[] {
18+
export function buildDataAtoms(count: number): PrimitiveAtom<Data>[] {
6919
const data = new Array(count);
7020
for (let i = 0; i < count; i++) {
71-
data[i] = {
72-
id: nextId++,
73-
label: `${A[random(A.length)]} ${C[random(C.length)]} ${
74-
N[random(N.length)]
75-
}`,
76-
};
21+
data[i] = atom({
22+
id: nextId++,
23+
label: `${A[random(A.length)]} ${C[random(C.length)]} ${
24+
N[random(N.length)]
25+
}`,
26+
});
7727
}
7828
return data;
7929
}
+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
const path = require("path");
2+
const webpack = require("webpack");
3+
4+
module.exports = {
5+
mode: "production",
6+
entry: {
7+
main: path.join(__dirname, "src", "main.tsx"),
8+
},
9+
output: {
10+
path: path.join(__dirname, "dist"),
11+
filename: "main.js",
12+
},
13+
resolve: {
14+
extensions: [".ts", ".tsx", ".js", ".jsx"],
15+
},
16+
module: {
17+
rules: [
18+
{
19+
test: /\.tsx?$/,
20+
loader: "babel-loader",
21+
exclude: /node_modules/,
22+
},
23+
],
24+
},
25+
plugins: [
26+
new webpack.DefinePlugin({
27+
"process.env": { NODE_ENV: JSON.stringify("production") },
28+
}),
29+
],
30+
};

0 commit comments

Comments
 (0)