32
loading...
This website collects cookies to deliver better user experience
const [count, setCount] = React.useState(0);
const [filter, setFilter] = React.useState('none');
const [filteredItems, setFilteredItems] = React.useState(props.items);
function onFilterChange(newFilter) {
setFilter(newFilter);
setFilteredItems(
props.items.filter(item => item.someProperty === newFilter)
);
}
const [filter, setFilter] = React.useState('none');
const filteredItems = React.useMemo(() =>
items.filter(item => item.someProperty === newFilter),
[props.items, filter]
);
function onFilterChange(newFilter) {
setFilter(newFilter);
}
useReducer
hook!const [request, dispatch] = React.useReducer((state, action) => {
switch (action.type) {
case 'loading': return { state: 'loading' };
case 'success: return { state: 'success', data: action.data };
case 'error': return { state: 'error', error: action.error };
case 'reset': return { state: 'idle' };
default: throw new Error(`Unknown action ${action.type}`);
}
}, { state: 'idle' });
useState
calls, but when several changes happen at the same time, I tend to use useReducer
instead. Luckily, that doesn’t happen too often.const CommonAncestor = () => {
const [filter, setFilter] = React.useState('none');
return (
<div>
<FilterSelector filter={filter} setFilter={setFilter} />
<FilteredItems filter={filter} />
</div>
);
};
Provider
component and a hook to consume the context need to be added.const FilterContext = React.createContext();
const FilterProvider = (props) => {
const [filter, setFilter] = React.useState('none');
return (
<FilterContext.Provider value={{ filter, setFilter }} {...props} />
);
};
const useFilter = () => {
const context = React.useContext(FilterContext);
if (!context) {
throw new Error("Wrap your component in a FilterProvider");
}
return context;
};
const CommonAncestor = () => {
return (
<FilterProvider>
<FilterSelector />
<FilteredItems />
</FilterProvider>
);
};
FilterProvider
, and remove all props passed to the FilterSelector
and FilteredItems
. The latter two can now look like this:const FilterSelector = () => {
const { filter, setFilter } = useFilter();
return (...);
};
const FilteredItems = () => {
const { filter } = useFilter();
const items = getItemsSomehow();
const filteredItems = React.useMemo(
() => items.filter(item => item.someProperty === filter),
[filter, items]
);
return (...)
};
const cache = {};
const useFetch = (key, fetcher) => {
const [request, dispatch] = React.useReducer(
requestReducerFromEarlier,
{ state: 'idle' },
);
const goFetch = async () => {
try {
dispatch({ type: 'loading' });
const result = await fetcher(key);
dispatch({ type: 'success', data: result });
cache[key] = result;
} catch (e) {
dispatch({ type: 'error', error: e });
}
};
if (cache[key]) {
goFetch();
return { data: cache[key], ...request };
}
return request;
}