-1

问题

我有一个自定义钩子,用于在 'react-router-dom' 的位置和历史记录的帮助下更新url查询字符串。所以在组件中,每当我想添加一个新查询时,我都会使用这个钩子。在这个自定义钩子中,我使用了 useRef来避免更新自定义钩子,这样使用该钩子的组件就不会呈现,但是使用这个钩子的组件会在每次更改位置时呈现。

自定义挂钩以更新 url 中的查询字符串

import { useRef } from 'react'
import { useHistory, useLocation } from 'react-router-dom'

export const useUpdateQueryString = () => {
  const history = useHistory()
  const location = useLocation()

  const routerRef = useRef({ search: '', pathname: '' })

  useEffect(() => {
    routerRef.current = { pathname: location.pathname || '', search: location.search || '' }
  }, [location.pathname, location.search])

  const onUpdateQueryString = useCallback((newQueryObj) => {
    const newQueryParamString = setQueryStringValue(newQueryObj, routerRef.current.search)
    history.push(`${routerRef.current.pathname}${newQueryParamString}`)
  }, [])

  return {
    onUpdateQueryString
  }
}

使用这个钩子的组件

import React, { useCallback } from 'react'
import { getTestQueryObj, useTestQueryString } from 'utils/query-string'


const TestComponent: React.FC = () => {
  const { onUpdateQueryString } = useTestQueryString()

  const handleClick = useCallback(() => {
    onUpdateQueryString(getTestQueryObj())
  }, [])

  console.log('TestComponent rendered')
  return <div onClick={handleClick}>{'Hello Component'}</div>
}

export default React.memo(TestComponent)

注意:getQueryObj是获取查询 obj 的函数,而setQueryObj是另一个获取查询 obj 并返回字符串的函数

4

1 回答 1

0

正如您在此处看到的,我没有使用 react-router-dom 中的 useLocation 来渲染所有使用它的组件,而是使用了窗口位置。我的组件只需要一个钩子即可将查询参数添加到该位置。很少有组件需要有关位置更改的信息,因此创建了另一个挂钩来观察位置更新。

const location = useLocation()
// Hook
export const useUpdateQueryString = () => {
  const history = useHistory()

  const onAddQueryString = (newQueryObj: Record<string, unknown>) => {
    const newLocationWithQueryParams = addQueryToLocation(newQueryObj)
    history.push(`${newLocationWithQueryParams}`)
  }

  return {
    onAddQueryString,
    onDeleteQueryStrings,
  }
}

// Method to add query to the location url
const addQueryToLocation = (value: Record<string, unknown>): string => {
  const location = window.location
  const existingQueryParamString = location.hash.split('?')[1] || ''
  const values = qs.parse(existingQueryParamString, { sort: false })
  const newQsValue = qs.stringify({ ...value, ...values }, { sort: false })
  return `?${newQsValue}`
}

https://codesandbox.io/s/pedantic-mountain-zmv4qn

您可以检查链接,现在只要查询参数发生更改,只会呈现组件 3。

于 2022-02-24T20:19:23.890 回答