const [createAssetMutation, createAssetMutationResult] = useMutation(
CREATE_ASSET_MUTATION,
{
update(cache, result) {
cache.modify({
id: "Project:" + projectId,
fields: {
assets: (previousData, { toReference }) => {
return [...previousData, toReference(result.data.createAsset)];
},
},
});
},
}
);
I have a mutation that creates asset inside project, i wanted to add the created asset inside project assets field in cache. I tried to do that cache is updated but the component not re-rendered.
Can anyone help me how to proper write the new data to cache and re-render the component?
lenz
June 21, 2023, 1:30pm
2
Can you show the code of the component that is not rerendering?
i’m using lazyQuery
const [fetchProjectAssets, { data, error, refetch }] = useLazyQuery<
SingleProjectQueryGqlResponse,
SingleProjectQueryGqlVariable
>(SingleProjectQueryGql);
lenz
June 23, 2023, 9:07am
4
Please show the full component, as well as the queries, not just the variable names. It’s really hard to get a full picture with this little information.
Here is the component
export default function Projects() {
const [fetchProjects, { data }] = useLazyQuery<
UserProjectsQueryClientGqlResponse,
UserProjectsQueryClientGqlVars
>(UserProjectsQueryClientGql);
const [projects, setProjects] = useState<Partial<DashboardProject>[]>([]);
const { setPageFilterConfigs } = useFilters();
useEffect(() => {
//setting projects
if (data?.projects) {
setProjects(data.projects);
}
}, [data?.projects]);
useEffect(() => {
//this filter config is runs first time automatically when the page is loaded
//this is for filter configs
setPageFilterConfigs(FilterTypes.dashboard, {
fetch: (variables) => fetchProjects(variables),
searchStringVariable: "searchKeyword",
//default variables
defaultVariables: {
states: ProjectStateEnum.Active,
},
});
}, []);
return (
<div className="main-wrapper">
{projects?.map((project) => (
<div key={project.id} className="project-container">
<h1>{project.name}</h1>
<div className="assets">
{project.assets?.map((asset) => (
<div key={asset.id}>{asset.name}</div>
))}
</div>
</div>
))}
</div>
);
}
Query:
const UserProjectsQueryClientGql = gql`
query UserProjectsQueryClient(
$searchKeyword: String = ""
$states: [ProjectStateType!]
) {
projects(
where: {
AND: [
{
OR: [
{ name: { contains: $searchKeyword, mode: insensitive } }
{
assets: {
some: {
name: { contains: $searchKeyword, mode: insensitive }
}
}
}
]
}
{ OR: [{ state: { in: $states } }] }
]
}
orderBy: [{ name: asc }]
) {
id
name
assets(orderBy: { position: asc }) {
id
name
}
}
}
`;
lenz
June 23, 2023, 1:46pm
6
Just to make sure it isn’t caused by that useEffect
+useState
combination, could you please replace that with
const projects = data?.projects || EMPTY_ARR;
where EMPTY_ARR
is a constant you define above your component like
const EMPTY_ARR = []
?
That is pretty much equivalent, but saves you one unnecessary rerender.
Also, if I might ask: how do you determine if the component rerenders? Have you placed a console.log(projects)
inside the component?
I have checked by doing the way you have told me, but didn’t work. if i return empty array from the cache modify then the component re-rendered, but whenever i’m adding new array with items it is not working.
re-rendered for this code
cache.modify({
id: "Project:" + projectId,
fields: {
assets: (previousData, { toReference }) => {
return [];
},
},
});