使用 GraphQL 获取的 useEffect 无限循环
我正在编写一个简单的 React hook,它从 GraphQL 端点获取一些数据,将结果存储在一个状态中,并在获取数据时返回 [fetched-data, true]
或 [null, false]
当没有数据时,您可以在像 const [data, returned] = useGraphql({ query, Variables }); 这样的组件中使用它。返回已加载?数据:'正在加载'
。
我遇到的问题是,如果我声明参数对象的可选变量属性,则挂钩会导致无限的 useEffect 循环。如果我省略变量参数,一切都会正常。
export default function useGraphql({ query, variables, token }: QueryArgs) {
const [data, setData] = useState(null)
const fetchData = useCallback(async () => {
const init: RequestInit = {
method: "POST",
headers: {
[token && 'Authorization']: token && `bearer ${token}`,
"Content-Type": "application/json",
"Accept": "application/json"
},
body: JSON.stringify({
query, variables
})
}
try {
const response: Response = await fetch('/graphql', init)
const parsed = await response.json()
setData(parsed.data)
} catch (error) {
console.log(error)
setData(null)
}
}, [query, variables, token]) // if I remove variables from the array here, this doesn't cause a loop anymore
useEffect(() => {
let mounted = true
if (mounted) {
fetchData()
}
return () => {
mounted = false
setData(null)
}
}, [fetchData])
if (data) {
for (const prop in data) {
return [data[prop], true]
break;
}
}
return [null, false]
}
当然,我在组件中使用这样的钩子:
const [data, loaded] = useGraphql({
query: `query ($email: String!) {
singleUser(email: $email) {
username
email
}
}`,
variables: {
email: "user1@project" // if I put variables like this, the loop occurs. If I hardcode the variables in the query, there is no loop.
}
})
return <span> {loaded ? data.email : 'loading'} </span>
我真的不明白为什么放置变量会导致无限的重新渲染。 variables
参数如何改变 fetchData
函数?
I am writing a simple react hook that fetches some data form a GraphQL endpoint, stores the result in a state and returns [fetched-data, true]
when the data is fetched or [null, false]
when there is no data so you can use it in components like const [data, loaded] = useGraphql({ query, variables }); return loaded ? data : 'loading'
.
The problem I am experiencing is that if I declare the optional variables property of the argument object, the hook causes an infinite useEffect loop. If I omit the variables argument, everything works fine.
export default function useGraphql({ query, variables, token }: QueryArgs) {
const [data, setData] = useState(null)
const fetchData = useCallback(async () => {
const init: RequestInit = {
method: "POST",
headers: {
[token && 'Authorization']: token && `bearer ${token}`,
"Content-Type": "application/json",
"Accept": "application/json"
},
body: JSON.stringify({
query, variables
})
}
try {
const response: Response = await fetch('/graphql', init)
const parsed = await response.json()
setData(parsed.data)
} catch (error) {
console.log(error)
setData(null)
}
}, [query, variables, token]) // if I remove variables from the array here, this doesn't cause a loop anymore
useEffect(() => {
let mounted = true
if (mounted) {
fetchData()
}
return () => {
mounted = false
setData(null)
}
}, [fetchData])
if (data) {
for (const prop in data) {
return [data[prop], true]
break;
}
}
return [null, false]
}
of course I am using this hook like this in a component:
const [data, loaded] = useGraphql({
query: `query ($email: String!) {
singleUser(email: $email) {
username
email
}
}`,
variables: {
email: "user1@project" // if I put variables like this, the loop occurs. If I hardcode the variables in the query, there is no loop.
}
})
return <span> {loaded ? data.email : 'loading'} </span>
I really don't understand why putting variables is causing infinite rerenders. How is variables
argument changing the fetchData
function?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我现在想出了以下解决方案:
我不传递普通变量对象,而是使用以下代码检查它是否已更改并将结果作为字符串返回。
所以在我的 useGraphql 钩子中,我像这样使用它:
它正在完成它的工作。我尝试返回一个对象而不是字符串化对象,但解析结果(使用
JSON.parse()
)仍然导致循环I came up with the following solution for now:
instead of passing the plain variables object, I check if it has changed with the following code and return the result as a string.
so in my
useGraphql
hook I use it like:and it is doing its job. I've tried to return an object instead of a stringified one but then the parsed result (with
JSON.parse()
) is still causing the loop