我正在使用可创建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
钩子没有在设置新的数据数组,它仅获取该数组的首字母并进行设置,但在更改时未设置新的数组。
有什么想法吗?
答案 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])
}