После нажатия на кнопку в Paginator срабатывает функция pageChanged. Она корректно передает значение currentPage из компонента Pagination. После чего выполняется функция fetchItems, которая должна выловить с апи нужные записи, но она вылавливает предыдущие записи, потому что стейт не успел почему то измениться. После повторного нажатия на кнопку уже показываются корректные данные.
Вот компонент
import React, { useEffect, useContext } from 'react'
import Loader from '../../components/UI/Loader/Loader'
import { Paginator } from '../../components/UI/Paginator/Paginator'
import { Layout } from '../Layout/Layout'
import { Card } from '../../components/Card/Card'
import { Alert } from '../../components/Alert/Alert'
import { ItemsContext } from '../../context/items/ItemsContext'
export const Items = () => {
const items = useContext(ItemsContext)
useEffect(() => {
items.fetchItems(true)
}, [])
const pageChanged = (index) => {
items.setCurrentPage(index)
items.fetchItems(false)
console.log('Items',index)
console.log('State',items.currentPage)
}
const renderCards = () => {
return items.items.map((item, index) => {
return (
<Card
key={item.id}
item={item}
// addItemToBasket={this.props.addItemToBasket}
id={index}
/>
)
})
}
return (
<Layout>
<Paginator
totalItemsCount={items.totalItemsCount}
pageSize={items.pageSize}
currentPage={items.currentPage}
pageChanged={pageChanged}
portionSize={3}
/>
<div className="card-group row">
{
items.loading || items.items.length === 0
? <Loader />
: renderCards()
}
</div>
<Alert />
</Layout>
)
}
Вот ItemsContext
import { createContext } from 'react'
export const ItemsContext = createContext()
Вот ItemsReducer
import {
SET_LOADING,
FETCH_ITEMS_SUCCESS,
FETCH_ERROR,
SET_CURRENT_PAGE,
SET_TOTAL_COUNT,
FETCH_ITEM_BY_ID_SUCCESS
} from '../types'
const handlers = {
[SET_LOADING]: state => ({...state, loading: true}),
[FETCH_ITEMS_SUCCESS]: (state, {payload}) => ({...state, items: payload, loading: false}),
[FETCH_ITEM_BY_ID_SUCCESS]: (state, {payload}) => ({...state, item: payload, loading: false}),
[FETCH_ERROR]: (state, {payload}) => ({...state, error: payload, loading: false}),
[SET_CURRENT_PAGE]: (state, {payload}) => ({...state, currentPage: payload}),
[SET_TOTAL_COUNT]: (state, {payload}) => ({...state, totalItemsCount: payload}),
DEFAULT: state => state
}
export const ItemsReducer = (state, action) => {
const handler = handlers[action.type] || handlers.DEFAULT
return handler(state, action)
}
Вот ItemsState
import React, { useReducer } from 'react'
import axios from 'axios'
import { ItemsContext } from './ItemsContext'
import { ItemsReducer } from './ItemsReducer'
import {
SET_LOADING,
FETCH_ITEMS_SUCCESS,
FETCH_ERROR,
SET_CURRENT_PAGE,
SET_TOTAL_COUNT,
FETCH_ITEM_BY_ID_SUCCESS
} from '../types'
export const ItemsState = ({ children }) => {
const initialState = {
items: [],
item: null,
pageSize: 3,
currentPage: 1,
totalItemsCount: 0,
loading: false,
error: null
// basket: []
}
const [state, dispatch] = useReducer(ItemsReducer, initialState)
const fetchItems = async bool => {
setLoading()
try {
console.log('ItemsState', state.currentPage)
const response = await axios.get(`https://reqres.in/api/users?page=${state.currentPage}&per_page=${state.pageSize}`)
fetchItemsSuccess(response.data.data)
if (bool) {
setTotalCount(response.data.total)
}
} catch (e) {
fetchError(e)
}
}
const fetchItemById = async id => {
setLoading()
try {
const response = await axios.get(`https://reqres.in/api/users/${id}`)
fetchItemByIdSuccess(response.data.data)
} catch (e) {
fetchError(e)
}
}
const fetchItemByIdSuccess = (item) => dispatch({ type: FETCH_ITEM_BY_ID_SUCCESS, payload: item })
const fetchItemsSuccess = (items) => dispatch({ type: FETCH_ITEMS_SUCCESS, payload: items })
const fetchError = (e) => dispatch({ type: FETCH_ERROR, payload: e })
const setCurrentPage = (currentPage) => {
dispatch({ type: SET_CURRENT_PAGE, payload: currentPage })
console.log('setCurrentPage', currentPage)
}
const setLoading = () => dispatch({ type: SET_LOADING })
const setTotalCount = (totalItemsCount) => dispatch({ type: SET_TOTAL_COUNT, payload: totalItemsCount })
const { items, item, pageSize, currentPage, totalItemsCount, loading } = state
return (
<ItemsContext.Provider value={{
fetchItems,
fetchItemById,
setCurrentPage,
setTotalCount,
items, item, pageSize, currentPage, totalItemsCount, loading
}}>
{children}
</ItemsContext.Provider>
)
}