My goal is to run the apollo query hook (useDataAboutThing
), get the part of the data
object I need, and get that resulting data into event
with setEvent
. Every attempt I try at solving this, I violate the law of hooks or create a feedback loop with useEffect
. This seems like it should be easy which probably means I have a flawed understanding of React that needs to be corrected.
type ComponentProps = {
id: number;
}
const Component = ({ id }: ComponentProps) => {
const { data, loading, error } = useDataAboutThing({
variables: {
id: id,
},
});
const [event, setEvent] = React.useState([]);
// without checking these, data is undefined
if (loading) return <div>Loading...</div>;
if (error) return <div>Error!</div>;
const dataInformation = data.information;
React.useEffect(() => {
setEvent(dataInformation)
}, []) // Error: Rendered more hooks than during the previous render.
// Adding this useEffect above the conditionals that check on error and loading also causes an error
return (
...
);
You could use onCompleted
to run some code when the query completes successfully:
type ComponentProps = {
id: number;
}
const Component = ({ id }: ComponentProps) => {
const [event, setEvent] = React.useState([]); // move this up here
const { data, loading, error } = useDataAboutThing({
variables: {
id: id,
},
onCompleted: (completedData) => { // onCompleted is a standard useQuery option
setEvent(completedData.information);
},
});
// without checking these, data is undefined
if (loading) return <div>Loading...</div>;
if (error) return <div>Error!</div>;
// now you don't need a useEffect here
return (
...
);
}
I would recommend using the above onCompleted
approach if possible, but if you’re curious how to make useEffect
work it would probably look something like this:
type ComponentProps = {
id: number;
}
const Component = ({ id }: ComponentProps) => {
const { data, loading, error } = useDataAboutThing({
variables: {
id: id,
},
});
const [event, setEvent] = React.useState([]);
React.useEffect(() => {
// optional chaining operator prevents error when data is undefined
if (data?.information) {
setEvent(data?.information);
}
}, [data?.information]);
if (loading) return <div>Loading...</div>;
if (error) return <div>Error!</div>;
return (
...
);
}