Spesification
Library
- @apollo/client": "^3.0.0"
- React.JS
GraphQL query : GET_ALL_USERS
query($input: GetAllUserInput) {
getAllUsers(input: $input) {
totalPages
currentPage
totalItems
rows {
email
username
created_dtm
status
group_id
}
}
}
GraphQL Mutation : DELETE_USER
mutation($username: String!) {
deleteUser(username: $username) {
username
}
}
Problem
1.When I'm click on Delete Button, UI doesn't update but in the backend, item successfully deleted
const TableUserInfo = ({ data }) => {
const [showModal, setShowModal] = useState(false);
const [username, setUsername] = useState("");
const handleShowModal = () => setShowModal(true);
const handleCloseModal = () => setShowModal(false);
const userIdtoDelete = data.getAllUsers.rows.map((row) => row.username);
const userIdToString = userIdtoDelete.toString();
const [deleteUser, { error, loading, refetch }] = useMutation(DELETE_USER, {
variables: { username: userIdToString },
update(cache, { data }) {
const { getAllUsers } = cache.readQuery({ query: GET_ALL_USERS });
cache.writeQuery({
query: GET_ALL_USERS,
data: {
getAllUsers: getAllUsers.filter(
(user) => user.username !== userIdToString
),
},
});
},
onCompleted: () => {
refetch();
},
one rror: (error) => {
console.log(JSON.stringify(error, null, 2));
},
});
...
<Button
key="Hapus"
variant="outline-danger"
onClick={deleteUser}
disabled={loading}
className="d-block btn-block btn-sm mb-2 w-100"
>
Hapus
</Button>
Additional Info : Data comes from parent. here is the parent code :
const PengaturanPengguna = () => {
// pagination
const [currentPage, setCurrentPage] = useState(1);
const sizeFetchDataPerPage = 10;
const { data, refetch, loading, error } = useQuery(GET_ALL_USERS, {
variables: {
input: {
size: sizeFetchDataPerPage,
page: currentPage,
},
},
});
const totalPages = data?.getAllUsers.totalPages;
useEffect(() => {
if (data) {
setCurrentPage(data?.getAllUsers.currentPage);
}
}, [data])
if (loading) return <p>Loading...</p>;
if (error)
return (
<p>
Error... {error.message} {console.log(JSON.stringify(error, null, 2))}{" "}
</p>
);
// refetch data
const handleRefreshClick = () => {
refetch();
};
return (
<Container>
<CardInfo data={data} />
<Card>
<Card.Title>
<span className="base-md text-regular mt-2 std-txt-primary-200">
Data Pengguna Dashboard
</span>
</Card.Title>
<Card.Body>
<div className="d-flex justify-content-between">
<Form inline>
<Search />
<Button variant='secondary' onClick={handleRefreshClick} disabled={loading}>{loading ? 'Loading...' : 'Muat Ulang'}</Button>
</Form>
<div>
<Button variant="success">Daftar Akun</Button>
</div>
</div>
<TableUserInfo data={data} /> //heres the table
<div className="d-flex justify-content-between">
<div className="align-self-center">
<span>Keterangan : </span>
<StyledDiv>
<Legend color="#40B4BA" />
<StyledSpan>Aktif</StyledSpan>
</StyledDiv>
<StyledDiv>
<Legend color="#78909C" />
<StyledSpan>Tidak Aktif</StyledSpan>
</StyledDiv>
</div>
<PageNavigator
totalPages={totalPages}
currentPage={currentPage}
setCurrentPage={setCurrentPage}
/>
</div>
</Card.Body>
</Card>
</Container>
);
};
What I've Tried I'm using refetchQueries, update method with cache.readQuery() and cache.writeQuery but UI still doesn't update.
Question How to make delete mutation deleted data in the backend and update the UI based on my query and mutation spesification ?
CodePudding user response:
maybe you are missing the rows here:
getAllUsers: {
...getAllUsers,
totalItems: getAllUsers.totalItems - 1,
rows: getAllUsers.rows.filter((user) => user.username !== userIdToString)
},
CodePudding user response:
When you read/write a query from the cache you must pass the same variables as the orinigal query, and to do that you can use the variables
returned from the original query:
Parent component
const { data, refetch, loading, error, variables } = useQuery(GET_ALL_USERS, {
variables: {
input: {
size: sizeFetchDataPerPage,
page: currentPage,
},
},
});
...
<TableUserInfo data={data} variables={variables} /> //heres the table
...
Child component
const TableUserInfo = ({ data, variables }) => {
...
const { getAllUsers } = cache.readQuery({ query: GET_ALL_USERS, variables });
cache.writeQuery({
query: GET_ALL_USERS,
variables,
data: {
getAllUsers: getAllUsers.filter(
(user) => user.username !== userIdToString
),
},
});
...
Also I think this part of the code is wrong:
const userIdtoDelete = data.getAllUsers.rows.map((row) => row.username);
const userIdToString = userIdtoDelete.toString();
...
data: {
getAllUsers: getAllUsers.filter(
(user) => user.username !== userIdToString
),
},
First you access row
property of getAllUsers
, you return an array of username
then you use .toString()
in this array, but when you update the cache you use .filter
directly on getAllUsers
and you compare the username
property with the stringified array of username
(userIdToString
), so I think you should verify this part for possible mistakes