Я постараюсь вам помочь
Прежде всего вам нужно извлечь редюсер из хука. Функция reducer
должна быть независимой от ловушки, потому что useReducer(reducer, initialState);
использует эти 2 параметра reducer
и initialState
только один раз и не обновляет их при каждом следующем вызове. В результате вы не можете использовать метод handlePageChange
внутри редуктора.
Второй момент - ваш редуктор должен возвращать данные с тем же интерфейсом, что и { data: Array, isLoading: Boolean }
. В вашем случае у вас есть 3 разных ответа от редуктора: после инициализации - { data: Array, loading: Boolean }
, после FETCHING
- { loading: Boolean }
и после DATA_RECEIVED
- { dataSource: Object, loading: Boolean, pagination: Object }
Я рекомендую вам не использовать useReducer. Я собираюсь предложить свою реализацию вашего кода
const useGridDataFetch = (fetcher, initialParams) => {
const { data, isLoading } = useGetData(fetcher, initialParams);
const { dataSource, pagination } = useGetPreparedData(data);
return {
isLoading,
dataSource,
pagination,
}
}
const useGetData = (fetcher, initialParams) => {
const [isLoading, setIsLoading] = useState(false);
const [data, setData] = useState({});
const location = useLocation();
useEffect(() => {
const params = {
...initialParams,
...queryString.parse(location.search)
}
setIsLoading(true);
fetcher({
...params,
page: params.page > 0 ? params.page - 1 : params.page
}, response => {
setData(response.data);
setIsLoading(false);
});
}, [location.search]);
return {
isLoading,
data
}
}
const useGetPreparedData = (data) => {
const location = useLocation();
const history = useHistory();
const handlePageChange = useCallback((page) => {
const qparams = queryString.parse(location.search);
const qs = Object.keys(qparams).map(key => key != 'page' ? `&${key}=${qparams[key]}` : '')
history.push(`${location.pathname}?page=${page}${qs.reduce((acc,val)=> acc + val , '')}`)
}, [location.pathname, location.search, history]);
return useMemo(() => {
if (!data.content) {
return {
dataSource: [],
pagination: {}
}
}
const pagination = {
pageSize: data.pageable.pageSize,
current: data.pageable.pageNumber + 1,
total: data.totalElements,
onChange: page => handlePageChange(page)
}
return {
dataSource: data.content,
pagination
};
}, [data, handlePageChange])
}
У меня могут быть некоторые ошибки с этим кодом, но я думаю, что основная идея проста