Thomas Bassetto
Senior Software Engineer
2020-10-22 / Thomas Bassetto
function App() {
const [data, setData] = React.useState(null);
React.useEffect(() => {
const fetchData = async () => {
const data = await fetchProduct();
setData(data);
};
fetchData();
}, []);
return (
<>
<h2>Product</h2>
{data && <p>{data.name}</p>}
</>
);
}
function App() {
const [data, setData] = React.useState(null);
const [isLoading, setIsLoading] = React.useState(false);
React.useEffect(() => {
const fetchData = async () => {
setIsLoading(true);
const data = await fetchProduct();
setData(data);
setIsLoading(false);
};
fetchData();
}, []);
return (
<>
<h2>Product</h2>
{(!isLoading && data) ? <p>{data.name}</p> : <p>Loading ...</p>}
</>
);
}
function App() {
const [data, setData] = React.useState(null);
const [isLoading, setIsLoading] = React.useState(false);
const [error, setError] = React.useState(null);
React.useEffect(() => {
const fetchData = async () => {
setError(null);
setIsLoading(true);
try {
const data = await fetchProduct();
setData(data);
} catch (error) {
setError(error);
}
setIsLoading(false);
};
fetchData();
}, []);
return (
<>
<h2>Product</h2>
{error && <div>Something went wrong ...</div>}
{(!isLoading && data) ? <p>{data.name}</p> : <p>Loading ...</p>}
</>
);
}
function App() {
const [status, setStatus] = React.useState("idle");
const [data, setData] = React.useState(null);
const [error, setError] = React.useState(null);
React.useEffect(() => {
const fetchData = async () => {
setError(null);
setStatus("loading");
try {
const data = await fetchProduct();
setData(data);
setStatus("success");
} catch (error) {
setError(error);
setStatus("failure");
}
};
fetchData();
}, []);
// ...
// ...
return (
<>
<h2>Product</h2>
{(() => {
if (status === "idle" || status === "loading") {
return <p>Loading ...</p>;
}
if (status === "failure") {
return <p>Something went wrong: {error}</p>;
}
if (status === "success") {
return <p>{data.name}</p>;
}
})()}
</>
);
}
const [state, setState] = React.useState({
status: 'idle',
data: undefined,
error: undefined
});
React.useEffect(() => {
const fetchData = async () => {
setState({
status: 'loading',
});
try {
const data = await fetchProduct();
setState({
status: 'success',
data: data,
});
} catch (error) {
setState({
status: 'error',
error: error,
});
}
};
fetchData();
}, []);
function App() {
const { status, data, error } = useProductApi();
return (
<>
<h2>Product</h2>
{(() => {
if (status === "idle" || status === "loading") {
return <p>Loading ...</p>;
}
if (status === "failure") {
return <p>Something went wrong: {error}</p>;
}
if (status === "success") {
return <p>{data.name}</p>;
}
})()}
</>
);
}
Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.
const useBetterProductApi = () => {
// ... useState
React.useEffect(() => {
let mounted = true;
const fetchData = async () => {
// ... setState
try {
const data = await fetchProduct();
if (!mounted) return;
// ... setState
} catch (error) {
if (!mounted) return;
// ... setState
}
};
fetchData();
return () => (mounted = false);
}, []);
return state;
};
function App() {
const { status, data, error } = useQuery("produt", () => fetchProduct());
return (
<>
<h2>Product</h2>
{(() => {
if (status === "idle" || status === "loading") {
return <p>Loading ...</p>;
}
if (status === "error") {
return <p>Something went wrong: {error}</p>;
}
if (status === "success") {
return <p>{data.name}</p>;
}
})()}
</>
);
}
Transport/protocol/backend agnostic data fetching (REST, GraphQL, promises, whatever!)
const { data } = useQuery('featuredServices', () => storeService.fetchPopularProducts(0, 3));
const popularProducts = data?.results ?? [];
const { data: categorization } = useQuery('categorization', () => storeService.fetchProductFilters(), {
initialData: {
categories: [],
industries: [],
productTypes: [],
providers: [],
},
initialStale: true,
});
import { useQuery } from 'react-query';
import { settingsService } from 'src/libs/settingsService/settingsService';
export const useCountryData = () => {
const { data: countryData, ...rest } = useQuery(
'countryData',
async () => {
const data = await settingsService.getCountryData();
data.sort((pre, next) => pre.name.localeCompare(next.name));
return data;
},
{
cacheTime: Infinity,
},
);
return { countryData, ...rest };
};
const [inputText, setInputText] = useState('');
const [debouncedInputText] = useDebounce(inputText, 200);
const { data, status, refetch } = useQuery(['searchbox', debouncedInputText], search, {
enabled: false, // do not make a request until we call refetch()
});
useEffect(() => {
if (debouncedInputText !== '') refetch();
}, [debouncedInputText, refetch]);
const { data, status, isFetchingMore, fetchMore, canFetchMore } = useInfiniteQuery(
['products', queryParams],
(_key, _q, page = 0) => {
return storeService.getProducts(queryParams.query, queryParams.sortBy, page);
},
{
getFetchMore: (lastData) => {
if ((lastData.pageIndex + 1) * lastData.pageSize < lastData.total) {
return lastData.pageIndex + 1;
}
return false;
},
},
);
{canFetchMore && (
<button disabled={!!isFetchingMore} onClick={fetchMore}>
{!isFetchingMore ? 'Load more' : 'Loading more...'}
</button>
)}
const queryCache = new QueryCache({
defaultConfig: {
queries: {
refetchOnWindowFocus: false,
},
},
});
<ReactQueryCacheProvider queryCache={queryCache}>
{/* App */}
</ReactQueryCacheProvider>
By Thomas Bassetto
Performant and powerful data synchronization for React