【问题标题】:What is the correct way to set state from another hook?从另一个钩子设置状态的正确方法是什么?
【发布时间】:2021-12-29 03:55:18
【问题描述】:

我有一个这样的查询参数:

const router = useRouter()
const { name } = router.query

我想使用这个name 并将其传递给具有状态的值:

const [queryName, setQueryName] = useState('')

问题是我不能将它作为默认值传递,如下所示:useState(name) 因为name 更新。

因此,我必须设置它,而不是使用 name 作为默认值。

setQueryName(name)

这也是无效的,我不能像这样在组件中设置它。

所以我必须使用useEffect

useEffect(() => {
    setQueryName(name)
}, [name])

但是这会触发无限错误:

已超过最大更新深度。当组件在 useEffect 中调用 setState 时,可能会发生这种情况,但 useEffect 要么没有依赖数组,要么每次渲染时其中一个依赖项都发生了变化。

从另一个钩子设置状态的正确方法是什么?

【问题讨论】:

  • 为什么不直接从router.query使用name
  • 我同意拉梅什的观点。将派生状态存储在本地组件状态中通常被认为是反模式。当您可以/应该只在组件中引用router.query.name 时,将name 保存到状态有什么意义/目的?
  • 假设我正在获取一个 URI 参数,然后使用该值来填充表单字段,并且该表单字段是可食用的,您会想要完全按照我正在做的事情做。我想做的不是那么激进。

标签: reactjs react-hooks next.js


【解决方案1】:

我相信这是做这种事情的最佳方式。

Next.js 路由器查询参数可以是string | string[],所以我将值包装在一个包裹useQueryParam 的备忘录中。

const useQueryParam = (value) => {
    return useMemo(() => (Array.isArray(value) ? value[0] : value) || '', [value])
}
const router = useRouter()
const queryName = useQueryParam(router.query.name)
const [name, setName] = useState('')
useEffect(() => setName(queryName), [queryName])

【讨论】:

  • 你试过const name = router.query.name吗?国家与它有什么关系?您还没有向我们展示用法,但它看起来像任何其他道具一样的道具。
【解决方案2】:

你可以做一个小技巧。

我想这会使代码更具可读性。您从 url 收到的值用作初始值,稍后可以通过页面中的某些 UI 进行更改,对吗?

const router = useRouter();
const { name: initialName } = router.query; // get name, but we'll be calling it "initialName" onward.

const [name, setName] = useState(initialName);

【讨论】:

  • 路由器值多次更新并触发,开始为null,然后有值。我相信这只会捕获第一个值并将其应用为默认值。
猜你喜欢
  • 2020-04-01
  • 2021-08-30
  • 2018-01-24
  • 1970-01-01
  • 2019-09-30
  • 1970-01-01
  • 2022-12-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多