My code: looks like
//GLOBAL STATE INITIALIZATION
const page = useSelector((state) => state.users.meta.page);
const perPage = useSelector((state) => state.users.meta.perPage);
const order = useSelector((state) => state.users.meta.order);
const dir = useSelector((state) => state.users.meta.dir);
const search = useSelector((state) => state.users.meta.search);
// FUNCTIONS
const fetchData = useCallback(
(
pageNumber = page,
pageSize = perPage,
columnOrder = order,
colDir = dir,
query = search
) => {
dispatch(
listUser(pageNumber, pageSize, columnOrder, colDir, searchColArr, query)
);
},
[searchColArr, dispatch]
);
//throwing warning above for missing dependencies
useEffect(() => {
dispatch(resetState(function () {}));
fetchData();
}, [dispatch, fetchData]);
Here, if I add the missing dependencies and replace [searchColArr, dispatch]
with [page, perPage, order, dir, searchColArr, search, dispatch]
then the program runs on infinite loop on. Becasuse, on listUser
action it dispatch
dispatch(
userActions.USER_LIST_SUCCESS({
list: data.data,
meta: data.meta,
})
);
and this USER_LIST_SUCCESS
will update redux state as:
USER_LIST_SUCCESS: (state, action) => {
state.list = action.payload.list;
state.meta = action.payload.meta;
state.isLoading = false;
},
and once this meta state got updated, the page, perPage, order, dir, search
will be updated as well and if I add these as dependencies, it fetchData again and while fetching data it update meta state and in this way infinite loops form.
What will be the best solution for this kind of situation? Or eslint-disable-line react-hooks/exhaustive-deps
is the only option?
Update: listUser
import user from "../../services/userService";
export const listUser =
(page, perPage, order, dir, searchCol, search) => async (dispatch) => {
try {
dispatch(
userActions.SET_IS_LOADING({
isLoading: true,
})
);
const { data } = await user.listUser(
page,
perPage,
order,
dir,
searchCol,
search
);
dispatch(
userActions.USER_LIST_SUCCESS({
list: data.data,
meta: data.meta,
})
);
} catch (error) {
toastify.error(error.response.data.message);
dispatch(
userActions.USER_LIST_FAIL({
errors:
error.response && error.response.data.errors
? error.response.data.errors
: error.response.data,
})
);
}
};
user.listUser
export async function listUser(
page,
perPage,
order,
dir,
searchColArr,
search
) {
let searchCol = JSON.stringify(searchColArr);
return httpClient.get(apiEndpoint, {
params: {
page,
perPage,
order,
dir,
searchCol,
search,
},
});
}
Update2
const handlePageChange = (pageNumber) => {
fetchData(pageNumber);
};
const handlePageLengthChange = (pageSize) => {
fetchData(null, pageSize);
};
const handleSort = (newOrder, newDir) => {
fetchData(null, null, newOrder, newDir);
};
I have a solution. That you will not pass page, perPage, order, dir, search
into listUser
. Just pass searchCol. Another param will get inside listUser
. You can update like this:
const fetchData = useCallback(() => {
dispatch(listUser(searchColArr));
}, [searchColArr, dispatch])
export const listUser =
( searchCol ) => async (dispatch, getState) => {
try {
dispatch(
userActions.SET_IS_LOADING({
isLoading: true,
})
);
const page = getState((state) => state.users.meta.page);
const perPage = getState((state) => state.users.meta.perPage);
const order = getState((state) => state.users.meta.order);
const dir = getState((state) => state.users.meta.dir);
const search = getState((state) => state.users.meta.search);
const { data } = await user.listUser(
page,
perPage,
order,
dir,
searchCol,
search
);
dispatch(
userActions.USER_LIST_SUCCESS({
list: data.data,
meta: data.meta,
})
);
} catch (error) {
toastify.error(error.response.data.message);
dispatch(
userActions.USER_LIST_FAIL({
errors:
error.response && error.response.data.errors
? error.response.data.errors
: error.response.data,
})
);
}
};
Update : If you still want to pass others params, you can check to get data.
listUser = (page, perPage, order, dir, searchCol, search) => async (dispatch, getState) => {
const page = page || getState((state) => state.users.meta.page);
...
};
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.