使用 GraphQL 提取的 useEffect 无限循环
useEffect infinite loop with GraphQL fetch
我正在编写一个简单的反应挂钩,它从 GraphQL 端点获取一些数据,将结果存储在状态中,并在获取数据时 returns [fetched-data, true]
或 [null, false]
没有数据,因此您可以在 const [data, loaded] = useGraphql({ query, variables }); return loaded ? data : 'loading'
.
等组件中使用它
我遇到的问题是,如果我声明参数对象的可选变量 属性,挂钩会导致无限的 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
函数?
我现在想到了以下解决方案:
我没有传递纯变量对象,而是使用以下代码检查它是否已更改,return 结果作为字符串。
function updateObj(obj: object): string {
let object: string = JSON.stringify(obj)
if (object !== JSON.stringify(obj)) {
object = JSON.stringify(obj)
}
return object
}
所以在我的 useGraphql
钩子中,我使用它:
const updatedVariables = updateObj(variables)
它正在做它的工作。我尝试 return 一个对象而不是一个字符串化的对象,但是解析结果(JSON.parse()
)仍然导致循环
我正在编写一个简单的反应挂钩,它从 GraphQL 端点获取一些数据,将结果存储在状态中,并在获取数据时 returns [fetched-data, true]
或 [null, false]
没有数据,因此您可以在 const [data, loaded] = useGraphql({ query, variables }); return loaded ? data : 'loading'
.
我遇到的问题是,如果我声明参数对象的可选变量 属性,挂钩会导致无限的 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
函数?
我现在想到了以下解决方案:
我没有传递纯变量对象,而是使用以下代码检查它是否已更改,return 结果作为字符串。
function updateObj(obj: object): string {
let object: string = JSON.stringify(obj)
if (object !== JSON.stringify(obj)) {
object = JSON.stringify(obj)
}
return object
}
所以在我的 useGraphql
钩子中,我使用它:
const updatedVariables = updateObj(variables)
它正在做它的工作。我尝试 return 一个对象而不是一个字符串化的对象,但是解析结果(JSON.parse()
)仍然导致循环