使用自定义钩子,我无法刷新/重新渲染组件

时间:2020-08-18 06:15:20

标签: javascript reactjs ecmascript-6

我正在使用可创建LOAD MORE功能的自定义挂钩:

import React from 'react'

export const useLoadMore = (data, postsPerPage = 12) => {
  const [postsToShow, setPostsToShow] = React.useState([])
  const [next, setNext] = React.useState(postsPerPage)

  const loopWithSlice = (start, end) => {
    const slicedPosts = data.slice(start, end)
    setPostsToShow([...postsToShow, ...slicedPosts])
  }

  React.useEffect(() => {
    loopWithSlice(0, postsPerPage)
  }, [])

  const handleShowMorePosts = () => {
    loopWithSlice(next, next + postsPerPage)
    setNext(next + postsPerPage)
  }

  return { handleShowMorePosts, postsToShow }
}

然后我需要按价格过滤数组,设置过滤器后,组件应重新渲染,但它没有这样做:

const Comp = ({ data }) => {

    const [filterBy, setFilter] = useState(null)
    const [defaultData, setData] = useState(get(data, 'products', []))
    
    const handleFilters = () => {
        let sorted = defaultData
    
        if (filterBy === 'high') {
          sorted = defaultData.sort(({ variants: [firstVariant] }, { variants: [secondVariant] }) => {
            return parseFloat(secondVariant.price) - parseFloat(firstVariant.price)
          })
        }
    
        return sorted
    }
    
    const { handleShowMorePosts, postsToShow } = useLoadMore(defaultData)
    
    useEffect(() => {
      setData(handleFilters())
    }, [filterBy, defaultData])
    
    return (<div>{postsToShow.map(...)}</div>)

}

handleFilters函数返回我需要的{price: "1250.00"},这是更高价格的输出。

我已经尝试了一些不同的方法,即使我在浏览器控制台中看到日志,该组件也没有重新呈现,但它似乎不起作用。

似乎useLoadMore钩子没有在设置新的数据数组,它仅获取该数组的首字母并进行设置,但在更改时未设置新的数组。

有什么想法吗?

1 个答案:

答案 0 :(得分:1)

useEffect无法检测到数组更改,因此一种方法是使用array.length作为依赖项

 React.useEffect(() => {
    loopWithSlice(0, postsPerPage, true)
    setNext(postsPerPage)

  }, [data.length])

但是这并不可靠,因为下一个过滤后的数据将具有相同的长度而无法正常工作。

更好地建议您向useLoadMore添加另一个参数, useLoadMore = (data, postsPerPage = 12, shouldReset) 并根据其更多地重置负载

 React.useEffect(() => {
    loopWithSlice(0, postsPerPage, true)
    setNext(postsPerPage)

  }, [shouldReset])

并使用按值过滤器作为其参数

 const { handleShowMorePosts, postsToShow } = useLoadMore(defaultData, 12, filterBy)

也可以使用JSON.stringify(data)作为依赖项。

 React.useEffect(() => {
    loopWithSlice(0, postsPerPage, true)
    setNext(postsPerPage)

  }, [JSON.stringify(data)])

如果是初次调用,请避免合并

  const loopWithSlice = (start, end, shouldReset) => {
    const slicedPosts = data.slice(start, end)
    if(shouldReset) {
      setPostsToShow(slicedPosts)
     } else {
      setPostsToShow([...postsToShow, ...slicedPosts])
    }