javascript - 使用自定义钩子我无法刷新/重新渲染组件
问题描述
我正在使用创建 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
钩子没有设置新的数据数组,它只抓取数组的初始值并设置它,但它在更改时没有设置新数组。
有任何想法吗?
解决方案
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])
}
推荐阅读
- math - 这个方程是什么意思 N(1 <= N <= 100)
- spring - 如何从多个 RepositoryItemReaders 读取并写入一个 RepositoryItemWriter
- c# - ExportRenderer 上的`System.Reflection.TargetInvocationExceptionExportRenderer`
- python - 从 Python 创建 PNG 文件并确保某些单元格是透明的
- javascript - 光滑的轮播:滑动可变数量的元素
- c# - 1 Uncaught (in promise) SyntaxError: Unexpected token 。在 JSON 中的位置 4
- c++ - 容器的模板化元素比较函数
- azure - Azure 上的 nginx 入口设置(不使用 helm)故障排除
- python - Py Selenium find elements inside element not working
- react-redux - Redux-Form 多行 Google Material UI TextField 在显示后不会自动调整大小