Execute react-apollo-hooks useQuery Only the First Time a Component Renders Idiomatically and Elegantly
Asked Answered
B

1

6

I'm using the most excellent react-apollo-hooks library, specifically the useQuery hook:

function Index() {
    ...
    const [dialogOpen, setDialogOpen] = useState({ show: false, id: '0' });
    ...   
    const { data, error } = useQuery(GET_JOBS, { suspend: true });
    if (error) {
        return <div>Error! {error.message}</div>;
    }
    const jobs = data.cxJobs; //This is our data
    ....
    function editCallback(e, more) {
        setDialogOpen({ show: true, id: e });
    }
....
}

Of course as soon as I change the dialogOpen state the component re-renders and the graphql query is executed again. Based on a suggestion on the library github repo I rewrote the code to set some state along with useEffect:

function Index() {
    ...
    const [dialogOpen, setDialogOpen] = useState({ show: false, id: '0' });
    const [jobs, setJobs] = useState([]);

    useEffect(_=> {fetchData()}, []);

    const fetchData = async _ => {
        const result = await client.query({query:GET_JOBS});
        setJobs(get(['data','cxJobs'], result));
    }

    async function onEventChanged(id, event) {
        await mutateOne(client, jobGQL, eventToJob(event));
    }
    ...
}

This is pretty good. But can I do better?

Bigler answered 9/5, 2019 at 17:6 Comment(0)
S
2

You could do something like this. Also, you might also want to avoid setting the result of the query to useState and just use data directly.

const [skip, setSkip] = React.useState(false)
const { loading, data } = useQuery(QUERY, { skip })

React.useEffect(() => {
  // check whether data exists
  if (!loading && !!data) {
    setSkip(true)
  }
}, [data, loading])

@Robert, I found that you have raised this issue on apollo-hooks github. And I found that there is an answer which helped me solve this issue, hence adding it here as well so that it can help someone else.

Showers answered 29/9, 2020 at 18:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.