Skip to content

Commit a114be6

Browse files
author
DESKTOP-E7TEPSG
committed
update Loger, changes useState and useEffect with more basic case, started useContext
1 parent dd69e4e commit a114be6

20 files changed

Lines changed: 1095 additions & 389 deletions

src/App.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import React from "react";
22
import "./App.css";
33
import examplesUseState1 from "./examples/use-state-1";
44
import examplesUseEffect1 from "./examples/use-effect-1";
5+
import examplesUseContext1 from "./examples/use-context-1";
56
import examplesUseRef1 from "./examples/use-ref-1";
67
import examplesHooksOrder from "./examples/hooks-order";
78
import examplesMemoization from "./examples/memoization";
@@ -18,6 +19,7 @@ const App: React.FC = () => {
1819
let examples: IExample[] = ([] as IExample[])
1920
.concat(examplesUseState1)
2021
.concat(examplesUseEffect1)
22+
.concat(examplesUseContext1)
2123
.concat(examplesUseRef1)
2224
.concat(examplesHooksOrder)
2325
.concat(examplesMemoization)

src/commons/ExampleBloc/index.tsx

Lines changed: 135 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,52 @@
1-
import React, { useContext, useMemo, useReducer } from "react";
1+
import React, { useContext, useMemo, useRef, useEffect, useState } from "react";
22
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";
33
import highlightStyle from "react-syntax-highlighter/dist/esm/styles/prism/tomorrow";
44
import Explanation from "../Explanation";
55
import Preface from "../Preface";
66
import cloneDeep from "lodash.clonedeep";
77

8-
export interface ILogger {
9-
log: (message: string, mixed?: any) => void;
10-
}
11-
12-
interface ILogs {
13-
logs: ILog[];
14-
id: number;
15-
}
16-
17-
interface ILog {
18-
id: number;
8+
interface Log {
199
message: string;
10+
fireDate: number;
11+
elapsedTime: number | null;
2012
mixed?: any;
21-
time: number;
2213
}
14+
type LogAction = (message: string, mixed?: any) => void;
15+
interface LogContext {
16+
action: LogAction;
17+
logs: React.MutableRefObject<Log[]>;
18+
observers: React.MutableRefObject<(() => void)[]>;
19+
}
20+
const LoggerContext = React.createContext<LogContext | null>(null);
21+
export const useLog = () => {
22+
const context = useContext(LoggerContext)!;
23+
useEffect(() => {
24+
const renderDate = Date.now();
25+
context.logs.current = context.logs.current.map(tLog => {
26+
return !tLog.elapsedTime ? {
27+
...tLog,
28+
elapsedTime: renderDate - tLog.fireDate
29+
} : tLog;
30+
});
31+
context.observers.current.forEach(observer => observer());
32+
});
2333

24-
const LoggerContext = React.createContext<ILogger | null>(null);
34+
return context.action;
35+
};
36+
const useLogObserver = () => {
37+
const context = useContext(LoggerContext)!;
38+
const [_, setTrigger] = useState<number>(0);
2539

26-
export const useLog = () => {
27-
return useContext(LoggerContext)!.log;
40+
useEffect(() => {
41+
const callback = () => {
42+
setTrigger(t => t + 1);
43+
}
44+
context.observers.current.push(callback);
45+
return () => {
46+
context.observers.current = context.observers.current.filter(observer => observer !== callback);
47+
};
48+
}, [context]);
49+
return context.logs.current;
2850
};
2951

3052
const Code = ({ code }: { code?: string | null }) => {
@@ -51,7 +73,9 @@ const Code = ({ code }: { code?: string | null }) => {
5173
);
5274
};
5375

54-
const Logs = ({ logs, clear }: { logs: ILog[]; clear: () => void }) => {
76+
const Logs = ({ clear }: { clear: () => void }) => {
77+
const logs = useLogObserver();
78+
5579
return (
5680
<div
5781
style={{
@@ -73,12 +97,12 @@ const Logs = ({ logs, clear }: { logs: ILog[]; clear: () => void }) => {
7397
{logs
7498
.map((log, i) => (
7599
<div
76-
key={log.id}
100+
key={i}
77101
style={{ margin: 10, borderBottom: "1px #EEE solid" }}
78102
>
79-
[<span style={{ fontWeight: "bold" }}>{log.id}</span>] (
103+
[<span style={{ fontWeight: "bold" }}>{i}</span>] (
80104
<span style={{ fontStyle: "italic" }}>
81-
+{log.time - (logs[i - 1] || log).time}ms
105+
+{log.elapsedTime || "..."}ms
82106
</span>
83107
) {log.message}
84108
<pre>{JSON.stringify(log.mixed, null, 2)}</pre>
@@ -178,39 +202,104 @@ const ExampleBloc = ({
178202
preface,
179203
explanation
180204
}: IProps) => {
181-
const [logs, dispatch] = useReducer(
182-
(logs: ILogs, action): ILogs => {
183-
switch (action.type) {
184-
case "add":
185-
return {
186-
logs: [...logs.logs, { ...action.payload, id: logs.id }],
187-
id: logs.id + 1
188-
};
189-
190-
case "clear":
191-
return { logs: [], id: 1 };
192-
193-
default:
194-
throw new Error("Not implemented: " + action.type);
195-
}
196-
},
197-
{ logs: [], id: 1 }
198-
);
205+
const logStorage = useRef<Log[]>([]);
206+
const logObservers = useRef<(() => void)[]>([]);
199207

200208
const memoComponent = useMemo(() => {
201209
const log = (message: string, mixed?: any) => {
202-
dispatch({
203-
type: "add",
204-
payload: { message, time: Date.now(), mixed: cloneDeep(mixed) }
205-
});
210+
const newLog: Log = {
211+
message: message,
212+
fireDate: Date.now(),
213+
elapsedTime: null,
214+
mixed: cloneDeep(mixed)
215+
};
216+
logStorage.current.push(newLog);
206217
};
207218

208219
return (
209-
<LoggerContext.Provider value={{ log }}>
210-
<Component />
220+
<LoggerContext.Provider value={{ action: log, logs: logStorage, observers: logObservers }}>
221+
<section
222+
style={{
223+
position: "relative",
224+
height: "100vh",
225+
width: "100%",
226+
margin: "40px 0",
227+
color: "#FFFFFF",
228+
backgroundColor: "#282c34",
229+
textAlign: "left",
230+
fontFamily:
231+
"-apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif"
232+
}}
233+
>
234+
<h3
235+
id={id}
236+
style={{
237+
margin: 10,
238+
padding: 10,
239+
borderBottom: "1px solid #61dafb",
240+
display: "flex",
241+
justifyContent: "space-between"
242+
}}
243+
>
244+
<a style={{ color: "#61dafb", textDecoration: "none" }} href={`#${id}`}>
245+
{title}
246+
</a>
247+
<div>
248+
{prev && (
249+
<a
250+
style={{
251+
color: "#61dafb",
252+
textDecoration: "none",
253+
margin: "0 10px"
254+
}}
255+
href={`#${prev}`}
256+
>
257+
258+
</a>
259+
)}
260+
{next && (
261+
<a
262+
style={{ color: "#61dafb", textDecoration: "none" }}
263+
href={`#${next}`}
264+
>
265+
266+
</a>
267+
)}
268+
</div>
269+
</h3>
270+
<div
271+
style={{
272+
display: "flex",
273+
flexDirection: "row",
274+
justifyContent: "space-around",
275+
position: "absolute",
276+
top: 50,
277+
bottom: 0,
278+
left: 0,
279+
right: 0
280+
}}
281+
>
282+
<Col percentage={40} margin={30}>
283+
<Code code={code} />
284+
</Col>
285+
286+
<Col percentage={40} margin={30}>
287+
<ComponentAndText preface={preface} explanation={explanation}>
288+
<Component />
289+
</ComponentAndText>
290+
</Col>
291+
292+
<Col percentage={20} margin={30}>
293+
<Logs clear={() => {
294+
logStorage.current = [];
295+
logObservers.current.forEach(observer => observer());
296+
}} />
297+
</Col>
298+
</div>
299+
</section>
211300
</LoggerContext.Provider>
212301
);
213-
}, []);
302+
}, [logStorage, logObservers, id, title, prev, next, code, preface, explanation]);
214303

215304
if (code) {
216305
code = code.replace(/\r/g, "");
@@ -219,84 +308,7 @@ const ExampleBloc = ({
219308
code = code.trim();
220309
}
221310

222-
return (
223-
<section
224-
style={{
225-
position: "relative",
226-
height: "100vh",
227-
width: "100%",
228-
margin: "40px 0",
229-
color: "#FFFFFF",
230-
backgroundColor: "#282c34",
231-
textAlign: "left",
232-
fontFamily:
233-
"-apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif"
234-
}}
235-
>
236-
<h3
237-
id={id}
238-
style={{
239-
margin: 10,
240-
padding: 10,
241-
borderBottom: "1px solid #61dafb",
242-
display: "flex",
243-
justifyContent: "space-between"
244-
}}
245-
>
246-
<a style={{ color: "#61dafb", textDecoration: "none" }} href={`#${id}`}>
247-
{title}
248-
</a>
249-
<div>
250-
{prev && (
251-
<a
252-
style={{
253-
color: "#61dafb",
254-
textDecoration: "none",
255-
margin: "0 10px"
256-
}}
257-
href={`#${prev}`}
258-
>
259-
260-
</a>
261-
)}
262-
{next && (
263-
<a
264-
style={{ color: "#61dafb", textDecoration: "none" }}
265-
href={`#${next}`}
266-
>
267-
268-
</a>
269-
)}
270-
</div>
271-
</h3>
272-
<div
273-
style={{
274-
display: "flex",
275-
flexDirection: "row",
276-
justifyContent: "space-around",
277-
position: "absolute",
278-
top: 50,
279-
bottom: 0,
280-
left: 0,
281-
right: 0
282-
}}
283-
>
284-
<Col percentage={40} margin={30}>
285-
<Code code={code} />
286-
</Col>
287-
288-
<Col percentage={40} margin={30}>
289-
<ComponentAndText preface={preface} explanation={explanation}>
290-
{memoComponent}
291-
</ComponentAndText>
292-
</Col>
293-
294-
<Col percentage={20} margin={30}>
295-
<Logs logs={logs.logs} clear={() => dispatch({ type: "clear" })} />
296-
</Col>
297-
</div>
298-
</section>
299-
);
311+
return <>{memoComponent}</>;
300312
};
301313

302314
export default ExampleBloc;
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import React from "react";
2+
import ActionButton from "../../commons/ActionButton";
3+
4+
interface CounterProps {
5+
counter: number;
6+
setCounter: (newCounter: number) => void;
7+
}
8+
9+
const CounterContext = React.createContext<CounterProps | null>(null);
10+
11+
const Displayer = () => {
12+
const context = React.useContext(CounterContext);
13+
if (context) return <pre>{JSON.stringify(context, null, 2)}</pre>;
14+
else return <></>;
15+
};
16+
const Consumer = () => {
17+
const context = React.useContext(CounterContext);
18+
19+
if (context)
20+
return (
21+
<ul>
22+
<li>
23+
<ActionButton
24+
label="Do nothing state-wise"
25+
onClick={() => {
26+
/* NOOP */
27+
}}
28+
/>
29+
</li>
30+
<li>
31+
<ActionButton
32+
label="Increment"
33+
onClick={() => {
34+
context.setCounter(context.counter + 1);
35+
}}
36+
/>
37+
</li>
38+
<li>
39+
<ActionButton
40+
label="Reset"
41+
onClick={() => {
42+
context.setCounter(0);
43+
}}
44+
/>
45+
</li>
46+
</ul>
47+
);
48+
else return <></>;
49+
};
50+
51+
const ExampleUseContext101 = () => {
52+
const [counter, setCounter] = React.useState<number>(0);
53+
54+
return (
55+
<>
56+
<CounterContext.Provider value={{ counter, setCounter }}>
57+
<Displayer />
58+
<Consumer />
59+
</CounterContext.Provider>
60+
</>
61+
);
62+
};
63+
64+
export default ExampleUseContext101;

0 commit comments

Comments
 (0)