Clean • Professional
function useFetch(url) {
const [data, setData] = useState(null);
useEffect(() => {
fetch(url)
.then(res => res.json())
.then(setData);
}, [url]);
return data;
}
| Feature | Custom Hook | HOC |
|---|---|---|
| Definition | Function that uses React hooks | Wrapper component |
| Complexity | Simple, functional | Can become nested |
| Reusability | High | High, but less readable |
function useFormValidation(initialValues, validate) {
const [values, setValues] = useState(initialValues);
const [errors, setErrors] = useState({});
const handleChange = (e) => {
const { name, value } = e.target;
setValues({ ...values, [name]: value });
setErrors(validate(values));
};
return { values, errors, handleChange };
}
function useDebounce(value, delay) {
const [debounced, setDebounced] = useState(value);
useEffect(() => {
const handler = setTimeout(() => setDebounced(value), delay);
return () => clearTimeout(handler);
}, [value, delay]);
return debounced;
}
<Parent>
<Child>
<GrandChild data={value} />
</Child>
</Parent>
const ThemeContext = React.createContext();
function App() {
return (
<ThemeContext.Provider value="dark">
<Child />
</ThemeContext.Provider>
);
}
function Child() {
const theme = useContext(ThemeContext);
return <div>{theme}</div>;
}createSlice() → concise reducersconfigureStore() → preconfigured storeMiddleware = logic between dispatch and reducer.
Example: redux-thunk for async calls.
const fetchData = () => (dispatch) => {
fetch("/api")
.then(res => res.json())
.then(data => dispatch({ type: "SET_DATA", payload: data }));
};
Selectors extract specific data from the state:
const selectUserName = (state) => state.user.name;
Reducers always return new state objects:
return { ...state, count: state.count + 1 };
| Type | Description |
|---|---|
| Server-side routing | Each navigation loads a new page from the server. |
| Client-side routing | React Router updates the view without reloading the page. |
<Route path="dashboard" element={<Dashboard />}>
<Route path="stats" element={<Stats />} />
</Route>
const navigate = useNavigate();
navigate("/login"); // replaces useHistory from v5
function PrivateRoute({ children }) {
return isLoggedIn ? children : <Navigate to="/login" />;
}
<Route path="/user/:id" element={<User />} />
function User() {
const { id } = useParams();
return <h1>User ID: {id}</h1>;
}
<Link> and <NavLink>?| Component | Purpose |
|---|---|
<Link> | Navigates to a route. |
<NavLink> | Same as <Link> but adds active class automatically. |
<Route path="*" element={<NotFound />} />
navigate("/profile", { state: { userId: 1 } });
const LazyPage = React.lazy(() => import("./Page"));
<Routepath="/lazy"
element={
<Suspense fallback={<div>Loading...</div>}>
<LazyPage />
</Suspense>
}
/>