繁体   English   中英

ReactQuery 和反冲为什么重新渲染太多

[英]ReactQuery and recoil why Too many re-renders

我正在与 reactquery 进行 api 通信,并使用反冲管理 state。
在reactQuery中,当status值为success时调用setRecoil。
我知道当原子值改变时它会被重新渲染......
如何解决无限渲染问题?
我不能在执行 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;
`

也许尝试添加这个:

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

在 useEffect 中:

useEffect(() => {
  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)
      }
}, [stockListQuery])

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM