Apollo React 为什么不能在 UseEffect hook 中查询
Apollo React Why Can't Query inside UseEffect hook
我刚开始学习 Apollo-React,但我无法发出 graphql 请求
这就是没有 Apollo 时我的做法
const Search = () => {
const [searchedText, setSearchedText] = React.useState('')
const [suggestions, setSuggestions] = React.useState([])
const [selected, setSelected] = React.useState(null)
const debounceHandler = (searchedText) => debounce(() => {
sendQuery(`{search(str:"${searchedText}") {name}}`).then(({search}) => {
if (!search) return
setSuggestions(search)
})
}, 500)
const handleInputChange = async (e) => {
if(e.key === 'Enter') {
const name = e.target.value
sendQuery(`{getPokemon(str:"${name}"){name, image}}`).then(({getPokemon}) => {
setSelected(getPokemon)
})
}
debounceHandler(searchedText)()
}
return (
<div>
<h1>Pokemon Search</h1>
<input type="text" value={searchedText} onChange={(e) => setSearchedText(e.target.value)} onKeyUp={(e) => handleInputChange(e)} style={{width:'100%'}} />
<hr />
<div>
{selected ? <PokemonProfile selected={selected} /> : suggestions.map(({name}) => (
<ShowSuggestion name={name} searchedText={searchedText} setSelected={setSelected}/>
)) }
</div>
</div>
)
}
现在没有我自己的 sendQuery 函数,我想使用 Apollo 的 useQuery 钩子。
const GET_POKEMON = gql`
query getPokemon ($str: String!) {
getPokemon(str: $str) {
name
image
}
}
`;
const SEARCH = gql `
query search($str: String!) {
search(str:$str) {
name
}
}
`;
这些是我在操场上正确的查询和结果。现在我再次编写搜索功能。我说每当 searchedText 发生变化时(当用户输入时),查询 Search 并将返回数据设置为建议。每当用户按下回车键时,我想从后端查询口袋妖怪并将其设置为选中状态。
const Search = () => {
const [searchedText, setSearchedText] = React.useState(null)
const [suggestions, setSuggestions] = React.useState([])
const [selected, setSelected] = React.useState(null)
React.useEffect(() => {
const { data } = useQuery(SEARCH, {
variables: { "str": searchedText },
pollInterval: 500,
});
if (data) {
setSuggestions(data)
}
}, [searchedText])
const fetchAndSelect = name => {
setSearchedText('')
const { pokemon } = useQuery(GET_POKEMON, {
variables: {
"str": name
}
})
setSelected(pokemon)
}
const handleInputChange = (e) => {
const name = e.target.value
if(e.key === 'Enter') {
return fetchAndSelect(name)
}
setSearchedText(name)
}
return (
<div>
<h1>Pokemon Search</h1>
<input type="text" value={searchedText} onKeyUp={(e) => handleInputChange(e)} style={{width:'100%'}} />
<hr />
<div>
{selected ? <PokemonProfile selected={selected} /> : suggestions.map(({name}) => (
<ShowSuggestion name={name} searchedText={searchedText} setSelected={setSelected}/>
))}
</div>
</div>
)
}
但这会导致 Invalid hook
调用错误。如果我不在 useEffect 中进行查询(我不确定这有什么问题?)这次我得到 Rendered more hooks than during the previous render.
错误。我不确定我做错了什么?
编辑
根据答案我编辑如下代码
const Search = () => {
const [searchedText, setSearchedText] = React.useState(null)
const [suggestions, setSuggestions] = React.useState([])
const [selected, setSelected] = React.useState(null)
const debouncedSearch = debounce(searchedText, 1000) // Trying to debounce the searched text
const [searchPokemons, { data }] = useLazyQuery(SEARCH);
const [getPokemon, { pokemon }] = useLazyQuery(GET_POKEMON)
React.useEffect(() => {
if (!searchedText) return
setSelected(null)
searchPokemons({ variables: { str: searchedText }})
if (data) {
console.log(data)
setSuggestions(data)
}
}, [debouncedSearch])
const fetchAndSelect = name => {
setSearchedText('')
getPokemon({variables: {str: name}})
if (pokemon) {
setSelected(pokemon)
}
}
const handleInputChange = (e) => {
const name = e.target.value
if(e.key === 'Enter') {
return fetchAndSelect(name)
}
setSearchedText(name)
}
return (
<div>
<h1>Pokemon Search</h1>
<input type="text" value={searchedText} onKeyUp={(e) => handleInputChange(e)} style={{width:'100%'}} />
<hr />
<div>
{selected ? <PokemonProfile selected={selected} /> : suggestions.map(({name}) => (
<ShowSuggestion name={name} searchedText={searchedText} setSelected={setSelected}/>
))}
</div>
</div>
)
}
我无法在输入法中输入任何内容。它像疯了一样吸引人。请帮忙
在这种情况下,您应该使用 useLazyQuery Hook。对于在未知时间点发生的事情非常有用,例如响应用户的搜索操作。
如果您在函数顶部调用 use 钩子并在 useEffect 钩子内部调用它,怎么样?
const [search, { data }] = useLazyQuery(SEARCH, {
variables: { "str": searchedText },
pollInterval: 500,
});
React.useEffect(() => {
if (searchedText)
search() // Function for executing the query
if (data)
setSuggestions(data)
}, [searchedText])
如您所见,useLazyQuery 以同步方式处理数据获取,没有任何承诺。
我刚开始学习 Apollo-React,但我无法发出 graphql 请求
这就是没有 Apollo 时我的做法
const Search = () => {
const [searchedText, setSearchedText] = React.useState('')
const [suggestions, setSuggestions] = React.useState([])
const [selected, setSelected] = React.useState(null)
const debounceHandler = (searchedText) => debounce(() => {
sendQuery(`{search(str:"${searchedText}") {name}}`).then(({search}) => {
if (!search) return
setSuggestions(search)
})
}, 500)
const handleInputChange = async (e) => {
if(e.key === 'Enter') {
const name = e.target.value
sendQuery(`{getPokemon(str:"${name}"){name, image}}`).then(({getPokemon}) => {
setSelected(getPokemon)
})
}
debounceHandler(searchedText)()
}
return (
<div>
<h1>Pokemon Search</h1>
<input type="text" value={searchedText} onChange={(e) => setSearchedText(e.target.value)} onKeyUp={(e) => handleInputChange(e)} style={{width:'100%'}} />
<hr />
<div>
{selected ? <PokemonProfile selected={selected} /> : suggestions.map(({name}) => (
<ShowSuggestion name={name} searchedText={searchedText} setSelected={setSelected}/>
)) }
</div>
</div>
)
}
现在没有我自己的 sendQuery 函数,我想使用 Apollo 的 useQuery 钩子。
const GET_POKEMON = gql`
query getPokemon ($str: String!) {
getPokemon(str: $str) {
name
image
}
}
`;
const SEARCH = gql `
query search($str: String!) {
search(str:$str) {
name
}
}
`;
这些是我在操场上正确的查询和结果。现在我再次编写搜索功能。我说每当 searchedText 发生变化时(当用户输入时),查询 Search 并将返回数据设置为建议。每当用户按下回车键时,我想从后端查询口袋妖怪并将其设置为选中状态。
const Search = () => {
const [searchedText, setSearchedText] = React.useState(null)
const [suggestions, setSuggestions] = React.useState([])
const [selected, setSelected] = React.useState(null)
React.useEffect(() => {
const { data } = useQuery(SEARCH, {
variables: { "str": searchedText },
pollInterval: 500,
});
if (data) {
setSuggestions(data)
}
}, [searchedText])
const fetchAndSelect = name => {
setSearchedText('')
const { pokemon } = useQuery(GET_POKEMON, {
variables: {
"str": name
}
})
setSelected(pokemon)
}
const handleInputChange = (e) => {
const name = e.target.value
if(e.key === 'Enter') {
return fetchAndSelect(name)
}
setSearchedText(name)
}
return (
<div>
<h1>Pokemon Search</h1>
<input type="text" value={searchedText} onKeyUp={(e) => handleInputChange(e)} style={{width:'100%'}} />
<hr />
<div>
{selected ? <PokemonProfile selected={selected} /> : suggestions.map(({name}) => (
<ShowSuggestion name={name} searchedText={searchedText} setSelected={setSelected}/>
))}
</div>
</div>
)
}
但这会导致 Invalid hook
调用错误。如果我不在 useEffect 中进行查询(我不确定这有什么问题?)这次我得到 Rendered more hooks than during the previous render.
错误。我不确定我做错了什么?
编辑
根据答案我编辑如下代码
const Search = () => {
const [searchedText, setSearchedText] = React.useState(null)
const [suggestions, setSuggestions] = React.useState([])
const [selected, setSelected] = React.useState(null)
const debouncedSearch = debounce(searchedText, 1000) // Trying to debounce the searched text
const [searchPokemons, { data }] = useLazyQuery(SEARCH);
const [getPokemon, { pokemon }] = useLazyQuery(GET_POKEMON)
React.useEffect(() => {
if (!searchedText) return
setSelected(null)
searchPokemons({ variables: { str: searchedText }})
if (data) {
console.log(data)
setSuggestions(data)
}
}, [debouncedSearch])
const fetchAndSelect = name => {
setSearchedText('')
getPokemon({variables: {str: name}})
if (pokemon) {
setSelected(pokemon)
}
}
const handleInputChange = (e) => {
const name = e.target.value
if(e.key === 'Enter') {
return fetchAndSelect(name)
}
setSearchedText(name)
}
return (
<div>
<h1>Pokemon Search</h1>
<input type="text" value={searchedText} onKeyUp={(e) => handleInputChange(e)} style={{width:'100%'}} />
<hr />
<div>
{selected ? <PokemonProfile selected={selected} /> : suggestions.map(({name}) => (
<ShowSuggestion name={name} searchedText={searchedText} setSelected={setSelected}/>
))}
</div>
</div>
)
}
我无法在输入法中输入任何内容。它像疯了一样吸引人。请帮忙
在这种情况下,您应该使用 useLazyQuery Hook。对于在未知时间点发生的事情非常有用,例如响应用户的搜索操作。
如果您在函数顶部调用 use 钩子并在 useEffect 钩子内部调用它,怎么样?
const [search, { data }] = useLazyQuery(SEARCH, {
variables: { "str": searchedText },
pollInterval: 500,
});
React.useEffect(() => {
if (searchedText)
search() // Function for executing the query
if (data)
setSuggestions(data)
}, [searchedText])
如您所见,useLazyQuery 以同步方式处理数据获取,没有任何承诺。