我正在尝试使用从GraphQL查询收集的数据更新状态。 我已经尝试过与https://www.apollographql.com/docs/react/data/queries/上的官方教程类似,标题为“手动执行查询”。
export default function SearchField() {
const [
searchInput,
setSearchInput
] = useState('');
const [
drinks,
setDrinks
] = useState(null);
const handleSubmit = (e) => {
e.preventDefault();
getDrinks({ variables: { cocktailName: searchInput } });
};
const [
getDrinks,
{ loading, data }
] = useLazyQuery(MULTIPLE_COCKTAILS_BY_NAME_QUERY);
if (loading)
return (
<div className="justify-content-center">
<p>Loading ...</p>
</div>
);
if (data && data.multipleCocktailsByName) {
setDrinks(data.multipleCocktailsByName);
}
return (...)
返回前的最后一部分使组件崩溃,并显示“错误:重新渲染太多。React限制了渲染次数以防止无限循环。”如果我改为尝试像这样更新handleSubmit中的状态:
const handleSubmit = (e) => {
e.preventDefault();
getDrinks({ variables: { cocktailName: searchInput } });
setDrinks(data.multipleCocktailsByName);
};
然后出现错误“无法读取未定义的属性'multipleCocktailsByName'”。我仍然设法从查询中有条件地呈现数据,但是处理状态很麻烦。我真的很感谢帮助此工作。
答案 0 :(得分:0)
在:
if (data && data.multipleCocktailsByName) {
setDrinks(data.multipleCocktailsByName);
}
成功运行查询并填充数据后,您将陷入无限循环,将酒水设定为该值。
您可以仅将数据用作组件状态(不用喝酒),然后执行以下操作:
if (loading) { ... } // render loading UI
if (error) { ... } // I suggest adding this so you can better debug.
if (data) { ... } // do what you intended to do with drinks but calling data.multipleCocktailsByName.
或者,您可以在“数据”上使用useEffect钩子来设置饮料状态,但这似乎是不必要的。
我应该补充,您的第二个示例失败,因为调用是异步的,因此调用后数据不会立即达到预期。这就是为什么,如果您想拥有一种饮料状态,则可以使用诸如以下的使用效果钩子:
useEffect(() => {
if (data && data.multipleCocktailsByName) {
setDrinks(data.multipleCocktailsByName
}
},[data, setDrinks])
然后仅在数据更改并包含一个值时设置饮料。
答案 1 :(得分:-1)
当前组件的问题是if
语句(在return
之前)将满足条件并更新每个渲染器的状态(一旦提交表单并{{1} }已执行-如useQuery
中现在有值)。
由于无论如何都是延迟加载数据,因此在提交表单时只需要更新组件的状态。将data
语句移至if
函数应该可以解决您的问题,并且不需要任何副作用(handleSubmit
)。
我在useEffect
函数上使用了async/await
,以确保查询在状态更新之前已经完成。
handleSubmit
有些事情需要考虑,您是否真的需要export default function SearchField() {
const [
searchInput,
setSearchInput
] = useState('');
const [
drinks,
setDrinks
] = useState(null);
const [
getDrinks,
{ loading, data }
] = useLazyQuery(MULTIPLE_COCKTAILS_BY_NAME_QUERY);
const handleSubmit = async (e) => {
e.preventDefault();
await getDrinks({ variables: { cocktailName: searchInput } });
if (data && data.multipleCocktailsByName) {
setDrinks(data.multipleCocktailsByName);
}
};
if (loading)
return (
<div className="justify-content-center">
<p>Loading ...</p>
</div>
);
return (...)
状态变量?如果您查看Apollo的drinks
和useQuery
示例,您会注意到它们通常只在return语句的JSX中直接使用useLazyQuery
变量。
通常这涉及一些条件渲染,尽管这在react组件中很常见。如果您没有在return语句之外的任何地方都未使用data
,请考虑进行重构以进行drinks
调用,并保存一两个重新渲染。