Apollo useLazyQuery调用后输入TextField触发Button onClick事件排查
问题触发原因
你看到的onClick自动触发是错觉,实际是查询逻辑自动执行导致的,核心原因有两个:
- 你在
useLazyQuery的初始化配置项中直接传入了依赖email状态的variables字段。Apollo Client的useLazyQuery在首次手动触发执行后,会默认监听配置项中variables的变化,只要variables的值更新(也就是你在TextField输入内容修改email状态时),就会自动重新发起查询,表现出来的效果和点击按钮触发查询完全一致。 - 额外可能性:如果你的组件外层包裹了
<form>标签,Material UI的Button组件默认type为submit,输入过程中如果触发了表单默认提交行为,也会执行查询逻辑。
排查方法
- 在
handleClick函数中加入打印日志,在TextField输入内容时观察控制台是否有对应日志输出,如果没有日志则可以确认onClick没有被触发,是useLazyQuery自动执行导致的问题。 - 在
useLazyQuery的配置项中加入onCompleted回调并打印日志,输入内容时如果触发了该回调,即可确认是查询自动执行导致的问题。
解决方案
方案1:调整useLazyQuery的变量传参逻辑
移除useLazyQuery初始化配置中的variables字段,改为在手动调用执行函数时传入变量,这样就不会触发变量变更自动重查的逻辑。
修改后的代码示例:
const component = (props) => { const [email, setEmail] = useState('') // 移除初始化配置中的variables const [getUserByEmail, { data, error, loading }] = useLazyQuery(userQuery); const handleClick = () => { // 调用时传入variables getUserByEmail({ variables: { userEmail: email, } }) } return ( <Grid item xs={12} className={props.classes.emailFormContainer}> <TextField className={props.classes.emailFieldContainer} onChange={e => setEmail(e.target.value)} /> <Button className={props.classes.button} onClick={handleClick} > Join Now </Button> </Grid> ) }
方案2:明确指定Button的type属性
如果组件外层有form标签,给Button明确设置type="button",避免触发表单默认提交行为:
<Button type="button" className={props.classes.button} onClick={handleClick} > Join Now </Button>
内容的提问来源于stack exchange,提问作者ZimZimma
相关产品推荐
相关产品推荐

