【问题标题】:How can I use the useQuery hook to populate state in other hooks?如何使用 useQuery 钩子在其他钩子中填充状态?
【发布时间】:2019-08-23 14:58:11
【问题描述】:

我最近一直在处理一些与钩子相关的问题,因为我一直在将钩子实现到我的项目中。我不断收到错误消息“渲染的钩子比上一次渲染时更多。”

似乎我可以让我的代码工作的唯一方法是将 useQuery 钩子放在所有其他钩子之后。然而这是一个问题,因为我想用查询数据中的值填充一些状态值。

// code that doesn't error, but am not able to initialize state with query values

const [url, setUrl] = useState('')

const updateLink = useMutation(LINK_UPDATE_MUTATION, {
  variables: {
    id: props.id,
    url
  }
})

const { data, loading, error } = useQuery(LINK_QUERY, {
  variables: {
    id: props.id
  }
})

if (loading) {
  return <div>Loading...</div>
}
if (error) {
  return <div>Error! {error.message}</div>
}

// code that errors with 'Rendered more hooks than during the previous render.'

const { data, loading, error } = useQuery(LINK_QUERY, {
    variables: {
      id: props.id
    }
  })

  if (loading) {
    return <div>Loading...</div>
  }
  if (error) {
    return <div>Error! {error.message}</div>
  }

const updateLink = useMutation(LINK_UPDATE_MUTATION, {
    variables: {
      id: props.id,
      url
    }
  })

const [url, setUrl] = useState(data.link.url)

我希望 useQuery 钩子可以用于使用其查询数据初始化其他值。

如果这还不够代码或需要更多解释,请告诉我。谢谢。

【问题讨论】:

    标签: reactjs react-apollo react-hooks


    【解决方案1】:

    您需要做的是在第一个钩子产生响应时更新状态。为此,您可以使用useEffect 钩子。您需要在功能组件的顶部渲染所有钩子。

    const [url, setUrl] = useState('')
    
    const updateLink = useMutation(LINK_UPDATE_MUTATION, {
      variables: {
        id: props.id,
        url
      }
    })
    
    const { data, loading, error } = useQuery(LINK_QUERY, {
      variables: {
        id: props.id
      }
    })
    
    useEffect(() => {
      if(data && data.link) {
        setUrl(data.link.url);
      }
    }, [data])
    
    if (loading) {
      return <div>Loading...</div>
    }
    if (error) {
      return <div>Error! {error.message}</div>
    }
    

    【讨论】:

    • 感谢您的回复。添加 useEffect 挂钩后,我现在收到错误“无法读取未定义的属性 'url'”。我相信这个错误表明数据库中的数据之前没有回来 --> useEffect(() =&gt; { setUrl(data.link.url) }, [data.link.url]) 我应该如何延迟 useEffect 挂钩,直到数据从数据库中返回? if (loading) 负责这一点,但如果我将 useEffect 钩子移到下面,我会继续收到与以前相同的错误。
    • useEffect 也在初始渲染上运行。此外,您必须将 data 作为键而不是 data.link.url 传递给 useEffect 依赖数组,然后检查效果中的数据值。我更新了答案以反映变化
    • @ShubhamKhatri 当data 是数组或对象时会发生什么?由于依赖数组只进行浅层比较,因此 useEffect 将在组件重新呈现时被调用,因为引用的值发生变化
    • @Luminusss,在这种情况下,您需要确保数据引用仅在更新其状态时才会更改,因为在上述情况下,useQuery 不会在每次运行时都返回新引用,它会无缝地工作
    【解决方案2】:

    你可以简单地按照这个方法,我也是这样做的。

      const client = useApolloClient();
      const [newData, setNewData] = useState(null);
      const [loading, setLoading] = useState(false);
    
      async function runQuery() {
        setLoading(true);
    
        const useQueryData = await client.query({
          query: SUBMITTED_ASSIGNMENTS, variables: {
            userId
          }
        });
        setNewData(useQueryData?.data?.assignments);
        console.log('newData', newData);
        setLoading(false);
      }
    
      useEffect(() => {
        runQuery();
      }, [newData]);
    

    【讨论】:

    • OP 的 useQuery 钩子有问题,这个答案甚至没有使用。
    猜你喜欢
    • 1970-01-01
    • 2020-05-23
    • 1970-01-01
    • 2021-12-31
    • 2020-10-19
    • 2021-03-02
    • 2020-08-11
    • 2020-11-15
    • 1970-01-01
    相关资源
    最近更新 更多