I am doing api communication with reactquery and managing the state with recoil.
In reactQuery, setRecoil is called when the status value is success.
I know it will be re-rendered when the atom value changes...
How can I solve the infinite rendering problem?
And can't I use destructuring assignment of an array when doing setRecoil?
import { StockAPI } from 'api/api'
import { IStock } from 'assets/type/stockType'
import Drawer from 'components/templates/Drawer/Drawer'
import produce from 'immer'
import _ from 'lodash'
import React, { useEffect, useState } from 'react'
import { useQuery } from 'react-query'
import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil'
import { drawerState, pageNumber } from 'store/CommonAtom/CommonAtom'
import {
searchProductCode,
searchProductName,
selectedLocation,
selectedState,
stockList,
} from 'store/StockAtom/StockAtom'
import styled from 'styled-components'
import { PER_PAGE } from 'utils/Const'
import StockFilterDrawer from '../components/organism/StockFilterDrawer/StockFilterDrawer'
import StockSearchHeader from '../components/organism/StockSearchHeader/StockSearchHeader'
import StockListTemplate from '../components/template/StockListTemplate'
function StockList() {
const setDrawerState = useSetRecoilState(drawerState)
const [loading, setLoading] = useState(true)
const [stocks, setStocks] = useRecoilState<IStock[]>(stockList)
const [page, setPage] = useRecoilState<number>(pageNumber)
const locationId = useRecoilValue(selectedLocation)
const state = useRecoilValue(selectedState)
const productName = useRecoilValue(searchProductName)
const productCode = useRecoilValue(searchProductCode)
const locationIdConvertToStr = locationId.join(',')
const param = {
page,
perPage: PER_PAGE,
...(!_.isEmpty(productName) && { name: productName }),
...(!_.isEmpty(productCode) && { productCode }),
...(!_.isEmpty(locationIdConvertToStr) && { locationId: locationIdConvertToStr }),
...(!_.isEmpty(state) && { state }),
}
console.log('current param', param)
const stockListQuery = useQuery('stockList', () => StockAPI.getStocks(param))
console.log('api result:', stockListQuery)
if (stockListQuery.isSuccess) {
console.log('here?')
const newStocks = produce(stocks, draftState => {
// eslint-disable-next-line no-param-reassign
return draftState.concat(stockListQuery.data)
})
console.log('immer', newStocks)
setStocks(newStocks)
}
// if (stockListQuery.status === 'success') {
// console.log('api result:', stockListQuery)
// const newStocks = [...stocks, ...stockListQuery.data]
// console.log(newStocks)
// const newStocks = [...stockListQuery.data]
// const test = stocks.concat(stockListQuery.data)
// console.log(newStocks)
// console.log('plz', newStocks)
// setStocks(stockListQuery.data)
// setStocks(test)
// }
const onClickFilter = () => {
return setDrawerState(prev => !prev)
}
const mockSelectList = [
{ label: 'productCode', value: 'productCode' },
{ label: 'productName', value: 'productName' },
]
// useEffect(() => {
// if (stockListQuery.isSuccess) {
// const newStocks = [...stocks, ...stockListQuery.data]
// setStocks(newStocks)
// }
// }, [stockListQuery.isSuccess])
useEffect(() => {
console.log(window.scrollY, document.documentElement.clientHeight, document.documentElement.scrollHeight)
function onScroll() {
if (window.scrollY + document.documentElement.clientHeight > document.documentElement.scrollHeight - 200) {
setPage(prev => prev + 1)
}
}
window.addEventListener('scroll', onScroll)
return () => {
window.removeEventListener('scroll', onScroll)
}
}, [page])
return (
<Container>
<StockListWrapper>
<StockListHeaderWrapper>
<StockSearchHeader onClickFilter={onClickFilter} mockSelectList={mockSelectList} />
</StockListHeaderWrapper>
<StockListContent>{stockListQuery.isSuccess && <StockListTemplate stocks={stocks} />}</StockListContent>
<Drawer>
<StockFilterDrawer />
</Drawer>
</StockListWrapper>
</Container>
)
}
export default StockList
const Container = styled.div`
margin: 0 auto;
// max-width: 1200px;
display: flex;
flex-direction: column;
// padding-top: 20px;
`
const StockListHeaderWrapper = styled.section`
padding: 10px 20px;
display: flex;
justify-content: space-between;
`
const StockListWrapper = styled.section`
width: 100%;
margin: 0 auto;
background-color: ${prop => prop.theme.colorPalette.bluegray.blueGray5};
border-radius: 10px;
`
const StockListContent = styled.section`
padding: 10px;
display: flex;
flex-direction: column;
gap: 10px;
`
Maybe try to add this:
inside a useEffect: