我有一个视图,是一个大的分页表。 我想在 URL 查询参数中包含页面索引,以便能够通过共享 URL 来共享表的特定页面。
我的问题是页面不是唯一的查询参数,所以我需要做的是,当页面更改时:
- 检索当前查询参数
- 从旧查询参数和新页面创建新的查询参数
- 更新查询参数。
但是,更新查询参数是一个问题,因为查询参数是检索旧参数的函数的依赖项,我被困在这个循环中。
我首先尝试做这样的事情:
import query from 'qs'
import { useLocation, useHistory } from 'react-router-dom'
function Comp() {
const [pageIndex, setPageIndex] = useState(0)
// Updates the query params using the provided ones.
const updateQueryParams = useCallback(
(pageIndex) => {
const oldSearch = query.parse(location.search, { ignoreQueryPrefix: true })
const newSearch = { ...oldSearch, pageIndex }
history.push({ pathname: location.pathname, search: query.stringify(newSearch) })
},
[location.search, location.pathname]
)
// Updates the query params when pageIndex changes.
useEffect(() => updateQueryParams(pageIndex), [updateQueryParams, pageIndex])
}
但是更新查询参数会更新location.search
这是updateQueryParams
回调的依赖项,它会触发无限循环。
我试图利用useRef
来存储搜索和路径名,手动更新它们,但我无法提出可行的解决方案。
我的最后一次尝试是在自定义钩子中提取逻辑,以将问题切成更小的部分(我将不得不在其他地方重用这段逻辑)。
此挂钩的当前状态为:
import { useLocation, useHistory } from 'react-router-dom'
import { useRef, useCallback } from 'react'
import query from 'qs'
export default function useQueryParams<QueryParams extends query.ParsedQs>(): [
QueryParams,
(newSearch: QueryParams) => void
] {
const location = useLocation()
const history = useHistory()
const search = useRef(query.parse(location.search, { ignoreQueryPrefix: true }) as QueryParams)
const pathname = useRef(location.pathname)
const setSearch = useCallback(
(newSearch: QueryParams) => {
history.push({ pathname: pathname.current, search: query.stringify(newSearch) })
search.current = newSearch
},
[history, pathname]
)
return [search.current, setSearch]
}
但这并不能解决我的问题。 尝试访问路由会触发无限循环,我在控制台中收到Warning: Maximum update depth exceeded
错误。
问题是由我的路线的声明方式引起的。
解决方案是从此模式更新我的所有路由:
<Route path="/login" component={Login} />
对此:
<Route path="/login">
<Login />
</Route>