V
V
vovashaplin2020-06-11 15:05:25
React
vovashaplin, 2020-06-11 15:05:25

How in useEffect to check whether both variables have changed or only one?

I fetch the data when I change the page in the paginator or change the selected categories.

useEffect(() => {
        fetchItems()
        // eslint-disable-next-line
    }, [currentPage, checkedList])

But when I am on the last page and remove a couple of categories, the number of pages naturally decreases, but I remain on the same page that goes beyond the paginator. Therefore, I want to make a change to this page, but when I do so, UseEffect is called twice because I have changed both the category and the page. What solution do you see?
All data is stored and transmitted through the context
import React, { useReducer } from 'react'
import PropTypes from 'prop-types'
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,
    SET_CHECKED_LIST
} from '../types'

export const ItemsState = ({ children }) => {
    const initialState = {
        items: [],
        item: null,
        pageSize: 9,
        currentPage: 1,
        totalItemsCount: 0,
        loading: false,
        error: null,
        checkedList: ['Apple','Samsung','HTC','Lenovo','Nokia']
    }

    const [state, dispatch] = useReducer(ItemsReducer, initialState)

    const fetchItems = async () => {
        setLoading()
        try {
            let fl = true
            let url = `http://localhost:8000/api/${state.checkedList}/${state.currentPage}/${state.pageSize}/`
            let urlLen = `http://localhost:8000/api/len/${state.checkedList}/`
            if (state.checkedList.length === 0) {
                url = `http://localhost:8000/api/null/${state.currentPage}/${state.pageSize}/`
                urlLen = `http://localhost:8000/api/len/null/`
                fl = false
            }

            const response = await axios.get(url)
            if (fl) {fetchItemsSuccess(response.data)} else fetchItemsSuccess([])
            const length = await axios.get(urlLen)
            setTotalCount(length.data[0].total)

        } catch (e) {
            fetchError(e)
        }
    }
    const fetchItemById = async id => {
        setLoading()
        try {
            const response = await axios.get(`http://localhost:8000/items/api/id/${id}/`)
            fetchItemByIdSuccess(response.data)
        } catch (e) {
            fetchError(e)
        }
    }

    const fetchItemByIdSuccess = (item) => dispatch({ type: FETCH_ITEM_BY_ID_SUCCESS, payload: item[0] })

    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 })

    const setLoading = () => dispatch({ type: SET_LOADING })

    const setTotalCount = (totalItemsCount) => dispatch({ type: SET_TOTAL_COUNT, payload: totalItemsCount })

    const setCheckedList = (checkedList) => dispatch({type: SET_CHECKED_LIST, payload: checkedList})

    const { items, item, pageSize, currentPage, totalItemsCount, loading, checkedList } = state

    return (
        <ItemsContext.Provider value={{
            fetchItems,
            fetchItemById,
            setCurrentPage,
            setTotalCount,
            setCheckedList,
            items, item, pageSize, currentPage, totalItemsCount, loading, checkedList
        }}>
            {children}
        </ItemsContext.Provider>
    )
}

ItemsState.propTypes = {
    children: PropTypes.element
}

Here is the reducer
import {
    SET_LOADING,
    FETCH_ITEMS_SUCCESS,
    FETCH_ERROR,
    SET_CURRENT_PAGE,
    SET_TOTAL_COUNT,
    FETCH_ITEM_BY_ID_SUCCESS,
    SET_CHECKED_LIST
} 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}),
    [SET_CHECKED_LIST]: (state, {payload}) => ({...state, checkedList: payload}),
    DEFAULT: state => state
} 

export const ItemsReducer = (state, action) => {
    const handler = handlers[action.type] || handlers.DEFAULT
    return handler(state, action)
}

5ee21df49914f966066331.png

Answer the question

In order to leave comments, you need to log in

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question