Skip to content

Instantly share code, notes, and snippets.

@savio777
Last active June 1, 2024 04:51
Show Gist options
  • Save savio777/057168ec69159e3f8ac2eac469e132a9 to your computer and use it in GitHub Desktop.
Save savio777/057168ec69159e3f8ac2eac469e132a9 to your computer and use it in GitHub Desktop.
React Hooks
import useCount from "./useCount";
function App() {
const {
count,
handleAddCount,
countRef,
handleAddCountRef,
reducer,
expensiveCount,
} = useCount();
const divRef = useRef<HTMLDivElement>(null);
// useLayoutEffect
useLayoutEffect(() => {
const rect = divRef.current?.getBoundingClientRect();
console.log("div height: ", rect.height);
}, []);
return (
<>
<h1>React Hooks</h1>
<div className="card">
<button onClick={handleAddCount}>count is {count}</button>
<button onClick={handleAddCountRef}>
count ref is {countRef.current}
</button>
<button onClick={() => reducer.dispatch({ type: "add" })}>
count reducer is {reducer.state}
</button>
<button>
expensive count {expensiveCount.toFixed(2).replace(".", ",")}
</button>
</div>
</>
);
}
export default App;
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App.tsx";
import "./index.css";
import { CountProvider } from "./useCount.tsx";
ReactDOM.createRoot(document.getElementById("root")!).render(
<React.StrictMode>
<CountProvider>
<App />
</CountProvider>
</React.StrictMode>
);
/* eslint-disable react-refresh/only-export-components */
import {
Dispatch,
MutableRefObject,
ReactNode,
createContext,
useCallback,
useContext,
useDebugValue,
useEffect,
useMemo,
useReducer,
useRef,
useState,
} from "react";
const INITIAL_COUNT = 0;
interface Props {
children: ReactNode;
}
interface IActionPayloadReducer {
type: "add" | "decrease";
}
interface IValues {
count: number;
countRef: MutableRefObject<number>;
handleAddCountRef: () => void;
handleAddCount: () => void;
expensiveCount: number;
reducer: {
state: number;
dispatch: Dispatch<IActionPayloadReducer>;
};
}
const reducer = (state: number, action: IActionPayloadReducer) => {
switch (action.type) {
case "add":
return state + 1;
case "decrease":
return state - 1;
default:
return state;
}
};
// context
export const CountContext = createContext<IValues>({} as IValues);
export const CountProvider = ({ children }: Props) => {
// useContext
console.log("context count");
// useState
const [count, setCount] = useState(INITIAL_COUNT);
const handleAddCount = useCallback(() => {
setCount((oldValue) => oldValue + 1);
}, []);
// useDebugValue
useDebugValue(count || "0 count"); // use with 'React Developer Tools' plugin
// useRef
const countRef = useRef(0);
const handleAddCountRef = () => countRef.current++; // don't re render on action
// useReducer
const [state, dispatch] = useReducer(reducer, INITIAL_COUNT);
// useMemo
const expensiveCount = useMemo(() => count * Math.random() * 10, [count]);
// useEffect
useEffect(() => {
const initData = async () => {
try {
const response = await fetch("https://api.github.com/users/savio777");
const responseJson = await response.json();
console.log("execute when component did mount", responseJson);
} catch (error) {
console.log({ error });
}
};
initData();
}, []);
useEffect(() => {
console.log("with each status update: ", count);
// execute when dismount
/*
return () => {
setCount(0);
};
*/
}, [count]);
return (
<CountContext.Provider
value={{
count,
handleAddCount,
countRef,
handleAddCountRef,
expensiveCount,
reducer: {
dispatch,
state,
},
}}
>
{children}
</CountContext.Provider>
);
};
const useCount = (): IValues => {
const context = useContext(CountContext);
if (!context) {
throw new Error("useI18N must be used within an I18nProvider");
}
return context;
};
export default useCount;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment