Reputation: 109
I'm writing a web app in React.js 18, and I've got an issue that I thought I could fix with lifting state, but it's not working.
The site functions to add polls on a topic. When I create a poll in my page, the list of polls on the page doesn't update until I do a refresh. I've tried lifting the state, but either I'm not doing it correctly or I'm having an asynchronous issue.
Here is the relevant code:
Here is in App.tsx:
function App() {
const [newPoll, setNewPoll] = useState(0);
return (
<div className="App">
<Header />
<Routes>
<Route path="/" element={<Home polls={samplePolls} />} />
<Route
path="/login"
element={
Auth.loggedIn() ? (
<Navigate to="/" replace={true} />
) : (
<Login setLogIn={setLoggedIn} />
)
}
/>
<Route
path="/:username/:pollname"
element={
<Poll
loggedin={loggedIn}
currUser={userInfo.username}
/>
}
/>
<Route path="/:username" element={<Profile />} />
<Route
path="/create"
element={
!Auth.loggedIn() ? (
<Navigate to="/" replace={true} />
) : (
<Create updateList={setNewPoll} currentList={newPoll} />
)
}
/>
<Route
path="/polls"
element={<Directory uvotes={userInfo.votes} newPoll={newPoll} />}
/>
<Route path="*" element={<Home polls={samplePolls} />} />
</Routes>
</div>
</ApolloProvider>
);
}
The state newPoll
and setNewPoll
is the lifted state. I pass setNewPoll
to the <Create />
page, and I pass newPoll
to the <Directory />
Within <Create />
, here is the quiz creation handler:
const handleCreate = async () => {
// handler for submission of quiz to be created
try {
const { data } = await addPoll({
variables: {
...
},
});
updateList(currentList + 1);
navigate(data.addPoll.redirect);
} catch (err: any) {
( error handling is here )
}
};
Within <Directory />
, I have this:
export function Directory({ uvotes, newPoll }: directoryProps) {
const { loading, data } = useQuery(QUERY_ALL_POLLS, {
variables: { ... },
});
const list = data?.getPolls.polls || false;
return (
<section id="directory" className={pollCount.created.toString()}>
<ul>
{list
? list.map((poll: userPollProps, index: number) => {
return <PollListing key={index} index={index} poll={poll} />;
})
: ""}
</ul>
</section>
);
}
So what I thought I was doing, was creating the state at the App level, handing the setting function to the creation function, handing the state value to the directory function, and on creation of the new poll I set the state to an essentially arbitrary value. What I expect is that immediately after creating the new poll, that if I go to the directory the new poll will be there...and it is not.
I also tried using Recoil.js, subscribing both pages to the atom, and arbitrarily changing the atom on creation...and that also didn't work.
Is there something I'm missing? Or is there a different and more relevant technique I should be using?
Upvotes: 0
Views: 61
Reputation: 109
It looks like the issue wasn't with react-router, or with state lifting, but with caching. I was able to find documentation for refetching queries in Apollo Server, and this worked well. One can define specific queries to be re-run following specific mutations in specific React components. Here I've done so with the ADD_POLL mutation in the create component:
const [addPoll] = useMutation(ADD_POLL, {
refetchQueries: [QUERY_ALL_POLLS],
});
Upvotes: 1