Reputation: 17701
I am trying to update the state (tableColumnConfiguration
) inside useEffect
and then pass on that state to the child component, but this code throws a "Maximum update depth exceeded" error and the app freezes without being able to click anything on screen.
const[environmentTableColumns, setEnvironmentTableCoulmns] = useState(environmentConditionsColumns);
const {
data: conditionTypeData,
loading: loadingConditionTypeData,
errorRedirect: conditionTypeDataErrorRedirect
} = useSectionEnumQuery('conditionType'); // this is API call
useEffect(() => {
if (conditionTypeData) {
let data;
let updatedEnvironmentColumnConfiguration = environmentConditionsColumns;
updatedEnvironmentColumnConfiguration = updatedEnvironmentColumnConfiguration.map(item => {
if (item.dataIndex === 'conditionType') {
data = conditionTypeData;
}
return data
? {
...item,
render: text => {
return renderEnum(text, data);
}
}
: item;
});
setEnvironmentTableCoulmns(updatedEnvironmentColumnConfiguration); // here i am setting the state
}
}, [conditionTypeData])
Child component :
<SpaceTypeTable
values={values}
isReadOnly={isReadOnly}
isProjectSystem={isProjectSystem}
tableTitle="Environment Criteria"
mappedLibrarySourceArray="environments"
sourceRender={p => renderGuidelineItem(p, true)}
tableColumns={environmentTableColumns} // here i am passing the column configuration
section={MASTER_SECTIONS.LIBRARY_ENVIRONMENT}
guidelines={guidelines}
form={form}
handleWarning={handleWarning}
/>
What's causing this useEffect
loop?
Update : UseSectionEnumQuery :
export const useSectionEnumQuery = resultFieldName => {
const { data: result, loading, error } = useQuery(ENUM_TYPES(resultFieldName));
const data = result?.[resultFieldName] && sortBy(result[resultFieldName], o => o.label);
const errorRedirect = error && errorRedirectElement(error, resultFieldName);
return { loading, data, errorRedirect };
};
Upvotes: 4
Views: 123
Reputation: 7239
This line is causing your problem.
const data = result?.[resultFieldName] && sortBy(result[resultFieldName], o => o.label);
data
will be a new reference each render and it's going to trigger your useEffect
every render because data
is conditionTypeData
and it's in your dependencies.
Can you try memoizing the value, so it only changes when result changes.
export const useSectionEnumQuery = resultFieldName => {
const { data: result, loading, error } = useQuery(ENUM_TYPES(resultFieldName));
const data = useMemo(() => result?.[resultFieldName] && sortBy(result[resultFieldName], o => o.label), [result, resultFieldName]);
const errorRedirect = useMemo(() => error && errorRedirectElement(error, resultFieldName), [error, resultFieldName]);
return { loading, data, errorRedirect };
};
Upvotes: 2