Skip to content

Commit 5ec0fa0

Browse files
committed
wip: added new base folder
1 parent 9d14bb1 commit 5ec0fa0

File tree

16 files changed

+899
-0
lines changed

16 files changed

+899
-0
lines changed
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Logs
2+
logs
3+
*.log
4+
npm-debug.log*
5+
yarn-debug.log*
6+
yarn-error.log*
7+
pnpm-debug.log*
8+
lerna-debug.log*
9+
10+
node_modules
11+
package-lock.json
12+
dist
13+
dist-ssr
14+
*.local
15+
16+
# Editor directories and files
17+
.vscode/*
18+
!.vscode/extensions.json
19+
.idea
20+
.DS_Store
21+
*.suo
22+
*.ntvs*
23+
*.njsproj
24+
*.sln
25+
*.sw?
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
6+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
7+
<title>Vite + React + TS</title>
8+
</head>
9+
<body>
10+
<div id="root"></div>
11+
<script type="module" src="/src/main.tsx"></script>
12+
</body>
13+
</html>
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"name": "simple-context",
3+
"private": true,
4+
"version": "0.0.0",
5+
"type": "module",
6+
"scripts": {
7+
"dev": "vite",
8+
"build": "tsc && vite build",
9+
"preview": "vite preview"
10+
},
11+
"dependencies": {
12+
"react": "^18.2.0",
13+
"react-dom": "^18.2.0"
14+
},
15+
"devDependencies": {
16+
"@types/react": "^18.0.17",
17+
"@types/react-dom": "^18.0.6",
18+
"@vitejs/plugin-react": "^2.1.0",
19+
"typescript": "^4.6.4",
20+
"vite": "^3.1.0"
21+
}
22+
}
Lines changed: 1 addition & 0 deletions
Loading

fast-context-generic-extended/src/App.css

Whitespace-only changes.
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import createFastContext from "./createFastContext";
2+
3+
const { Provider, useStore } = createFastContext({
4+
first: "",
5+
last: "",
6+
});
7+
8+
const TextInput = ({ value }: { value: "first" | "last" }) => {
9+
const [fieldValue, setStore] = useStore((store) => store[value]);
10+
return (
11+
<div className="field">
12+
{value}:{" "}
13+
<input
14+
value={fieldValue}
15+
onChange={(e) => setStore({ [value]: e.target.value })}
16+
/>
17+
</div>
18+
);
19+
};
20+
21+
const Display = ({ value }: { value: "first" | "last" }) => {
22+
const [fieldValue] = useStore((store) => store[value]);
23+
return (
24+
<div className="value">
25+
{value}: {fieldValue}
26+
</div>
27+
);
28+
};
29+
30+
const FormContainer = () => {
31+
return (
32+
<div className="container">
33+
<h5>FormContainer</h5>
34+
<TextInput value="first" />
35+
<TextInput value="last" />
36+
</div>
37+
);
38+
};
39+
40+
const DisplayContainer = () => {
41+
return (
42+
<div className="container">
43+
<h5>DisplayContainer</h5>
44+
<Display value="first" />
45+
<Display value="last" />
46+
</div>
47+
);
48+
};
49+
50+
const ContentContainer = () => {
51+
return (
52+
<div className="container">
53+
<h5>ContentContainer</h5>
54+
<FormContainer />
55+
<DisplayContainer />
56+
</div>
57+
);
58+
};
59+
60+
function App() {
61+
return (
62+
<Provider>
63+
<div className="container">
64+
<h5>App</h5>
65+
<ContentContainer />
66+
</div>
67+
</Provider>
68+
);
69+
}
70+
71+
export default App;
Lines changed: 1 addition & 0 deletions
Loading
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import React, {
2+
useRef,
3+
createContext,
4+
useContext,
5+
useCallback,
6+
useSyncExternalStore,
7+
} from "react";
8+
9+
export default function createFastContext<Store>(initialState: Store) {
10+
function useStoreData(): {
11+
get: () => Store;
12+
set: (value: Partial<Store>) => void;
13+
subscribe: (callback: () => void) => () => void;
14+
} {
15+
const store = useRef(initialState);
16+
17+
const get = useCallback(() => store.current, []);
18+
19+
const subscribers = useRef(new Set<() => void>());
20+
21+
const set = useCallback((value: Partial<Store>) => {
22+
store.current = { ...store.current, ...value };
23+
subscribers.current.forEach((callback) => callback());
24+
}, []);
25+
26+
const subscribe = useCallback((callback: () => void) => {
27+
subscribers.current.add(callback);
28+
return () => subscribers.current.delete(callback);
29+
}, []);
30+
31+
return {
32+
get,
33+
set,
34+
subscribe,
35+
};
36+
}
37+
38+
type UseStoreDataReturnType = ReturnType<typeof useStoreData>;
39+
40+
const StoreContext = createContext<UseStoreDataReturnType | null>(null);
41+
42+
function Provider({ children }: { children: React.ReactNode }) {
43+
return (
44+
<StoreContext.Provider value={useStoreData()}>
45+
{children}
46+
</StoreContext.Provider>
47+
);
48+
}
49+
50+
function useStore<SelectorOutput>(
51+
selector: (store: Store) => SelectorOutput
52+
): [SelectorOutput, (value: Partial<Store>) => void] {
53+
const store = useContext(StoreContext);
54+
if (!store) {
55+
throw new Error("Store not found");
56+
}
57+
58+
const state = useSyncExternalStore(
59+
store.subscribe,
60+
() => selector(store.get()),
61+
() => selector(initialState),
62+
);
63+
64+
return [state, store.set];
65+
}
66+
67+
return {
68+
Provider,
69+
useStore,
70+
};
71+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
body {
2+
font-family: Arial, Helvetica, sans-serif;
3+
padding: 1rem;
4+
}
5+
6+
.container {
7+
margin-top: 0.5rem;
8+
padding: 0.5rem 1.5rem;
9+
border: 1px solid #ccc;
10+
}
11+
12+
.field, .value {
13+
padding: 0.5rem;
14+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import React from 'react'
2+
import ReactDOM from 'react-dom/client'
3+
import App from './App'
4+
import './index.css'
5+
6+
ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
7+
<React.StrictMode>
8+
<App />
9+
</React.StrictMode>
10+
)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/// <reference types="vite/client" />
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"compilerOptions": {
3+
"target": "ESNext",
4+
"useDefineForClassFields": true,
5+
"lib": ["DOM", "DOM.Iterable", "ESNext"],
6+
"allowJs": false,
7+
"skipLibCheck": true,
8+
"esModuleInterop": false,
9+
"allowSyntheticDefaultImports": true,
10+
"strict": true,
11+
"forceConsistentCasingInFileNames": true,
12+
"module": "ESNext",
13+
"moduleResolution": "Node",
14+
"resolveJsonModule": true,
15+
"isolatedModules": true,
16+
"noEmit": true,
17+
"jsx": "react-jsx"
18+
},
19+
"include": ["src"],
20+
"references": [{ "path": "./tsconfig.node.json" }]
21+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"compilerOptions": {
3+
"composite": true,
4+
"module": "ESNext",
5+
"moduleResolution": "Node",
6+
"allowSyntheticDefaultImports": true
7+
},
8+
"include": ["vite.config.ts"]
9+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { defineConfig } from 'vite'
2+
import react from '@vitejs/plugin-react'
3+
4+
// https://vitejs.dev/config/
5+
export default defineConfig({
6+
plugins: [react()]
7+
})

0 commit comments

Comments
 (0)