patternjavascriptreactModeratepending
React custom hook composition patterns
Viewed 0 times
custom hooksuseAsyncuseLocalStoragehook compositionreusable logic
Problem
Need to extract and compose reusable stateful logic across React components.
Solution
Patterns for composing custom hooks:
// 1. Data fetching hook
function useAsync(asyncFn, deps = []) {
const [state, setState] = useState({
data: null, error: null, loading: true
});
useEffect(() => {
let cancelled = false;
setState(s => ({ ...s, loading: true }));
asyncFn()
.then(data => !cancelled && setState({ data, error: null, loading: false }))
.catch(error => !cancelled && setState({ data: null, error, loading: false }));
return () => { cancelled = true; };
}, deps);
return state;
}
// 2. Local storage hook
function useLocalStorage(key, initialValue) {
const [value, setValue] = useState(() => {
const stored = localStorage.getItem(key);
return stored ? JSON.parse(stored) : initialValue;
});
useEffect(() => {
localStorage.setItem(key, JSON.stringify(value));
}, [key, value]);
return [value, setValue];
}
// 3. Composed hook: persistent async data
function usePersistedQuery(key, queryFn) {
const [cached, setCached] = useLocalStorage(key, null);
const { data, error, loading } = useAsync(queryFn, [key]);
useEffect(() => {
if (data) setCached(data);
}, [data]);
return { data: data || cached, error, loading };
}
// 4. Media query hook
function useMediaQuery(query) {
const [matches, setMatches] = useState(
() => window.matchMedia(query).matches
);
useEffect(() => {
const mql = window.matchMedia(query);
const handler = (e) => setMatches(e.matches);
mql.addEventListener('change', handler);
return () => mql.removeEventListener('change', handler);
}, [query]);
return matches;
}Why
Custom hooks extract stateful logic into reusable functions. Composing hooks builds complex behavior from simple, tested building blocks.
Context
React applications with reusable stateful patterns
Revisions (0)
No revisions yet.