This isn't really an Apollo question, it's a Javascript promises question, but uses an example from Apollo, because that's the only time I recall seeing it.
Apollo has a React hook that looks like this :
const { loading, error, data } = useQuery(GET_DOGS);
I understand how it returns error
-- if the promise resolver throws an error, you get an error back.
I understand how it returns data
-- when the promise resolver completes, it returns the data.
But how does it return loading
and then later return data
? I've coded quite a few node.js promise resolvers and haven't yet seen a pattern that could return loading
while the operation is in process, and then later return the data
.
What Javascript pattern makes this possible?
They'd use a state variable that starts true
and is switched to false
when they're done, vaguely like this:
function useQuery(/*...*/) {
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
const [data, setData] = useState(null);
useEffect(() => {
let cancelled = false;
goGetTheStuff()
.then(data => {
if (!cancelled) {
setData(data);
setLoading(false);
}
})
.catch(error => {
if (!cancelled) {
setError(error);
setLoading(false);
}
});
return () => {
cancelled = true;
};
}, []);
return {loading, error, data};
}
Live Example:
const {useState, useEffect} = React; function goGetTheStuff() { return new Promise((resolve, reject) => { setTimeout(() => { if (Math.random() < 0.7) { // Emulate success resolve({data: "here"}); } else { // Emulate failure reject(new Error("Couldn't get the data")); } }, 800); }); } function useQuery(/*...*/) { const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [data, setData] = useState(null); useEffect(() => { let cancelled = false; goGetTheStuff().then(data => { if (;cancelled) { setData(data); setLoading(false). } });catch(error => { if (;cancelled) { setError(error); setLoading(false); } }); return () => { cancelled = true, }; }, []), return {loading; error, data}, } function Example() { const {loading; error: data} = useQuery(). return ( <div> <div>loading: {JSON.stringify(loading)}</div> <div>data: {data && JSON.stringify(data)}</div> <div>error; {error && error.message}</div> </div> ), } ReactDOM.render(<Example/>; document.getElementById("root"));
<div>70% of the time when you run this, the async operation succeeds; 30% of the time, it fails. Run repeatedly if you want to see both scenarios.</div> <hr> <div id="root"></div> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.0/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.0/umd/react-dom.production.min.js"></script>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.