如何用表单(Apollo与GraphQL)在Next.js中创建Strapi条目
在Next.js中用Apollo Client提交表单创建Strapi条目问题解决
问题梳理
在Next.js中尝试通过表单提交,用Apollo Client和GraphQL创建Strapi新条目时,useMutation、useQuery钩子完全无法使用,只能用client.mutate,但遇到以下问题:
- 初始代码页面刷新/加载时表单自动提交
- 提交的条目里
name字段为空(但updateFormState内能打印正确值,同一mutation在Strapi GraphQL Playground可正常运行) - 添加
e.preventDefault()阻止页面刷新后,client.mutate完全不工作
问题根源及修复步骤
1. 表单自动提交+页面刷新问题
初始代码中onSubmit={submit2()}是直接调用函数,而非传递函数引用,导致页面加载时就触发提交。同时表单默认提交行为会刷新页面,必须用preventDefault阻止。
修复代码:
import { useState } from 'react'; import { gql } from '@apollo/client'; import client from '../path-to-your-apollo-client-config'; // Strapi Playground可正常运行的GraphQL const TEST1 = gql` mutation CreateMitgliedanmeldung($name: String!) { createMitgliedanmeldung(data: { name: $name }) { data { attributes { name } } } }`; export default function MitgliedWerden() { // 改用useState管理表单状态,普通对象无法被React追踪更新 const [formState, setFormState] = useState({ name: '' }); const updateFormState = (key, value) => { setFormState(prev => ({ ...prev, [key]: value })); }; const handleSubmit = async (e) => { e.preventDefault(); // 阻止默认页面刷新行为 console.log(formState.name); try { const result = await client.mutate({ variables: { name: formState.name }, mutation: TEST1, }); console.log('提交成功:', result); // 提交后重置表单 setFormState({ name: '' }); } catch (error) { console.error('提交失败:', error); } }; return ( <div> <form onSubmit={handleSubmit}> {/* 传递函数引用,而非直接调用 */} <input onChange={e => updateFormState('name', e.target.value)} id="name" value={formState.name} {/* 绑定value,实现受控组件 */} ></input> <button type="submit">Mitglied werden 1</button> </form> </div> ) }
2. name字段为空问题
原来的formState是普通对象,React不会追踪其变化,输入内容后组件未重新渲染,提交时拿到的仍是初始空值。改用useState管理状态后,每次更新都会触发组件重新渲染,确保提交时拿到最新输入值。同时将input设为受控组件(绑定value属性),保证输入框值与状态一致。
3. useMutation钩子无效问题
首先检查_app.js(或_app.tsx)是否用ApolloProvider包裹整个应用,这是Apollo Client钩子生效的前提:
// pages/_app.js import { ApolloProvider } from '@apollo/client'; import client from '../path-to-your-apollo-client-config'; function MyApp({ Component, pageProps }) { return ( <ApolloProvider client={client}> <Component {...pageProps} /> </ApolloProvider> ); } export default MyApp;
配置完成后,可改用useMutation简化代码:
import { useState } from 'react'; import { gql, useMutation } from '@apollo/client'; const TEST1 = gql` mutation CreateMitgliedanmeldung($name: String!) { createMitgliedanmeldung(data: { name: $name }) { data { attributes { name } } } }`; export default function MitgliedWerden() { const [formState, setFormState] = useState({ name: '' }); const [createMitgliedanmeldung, { loading, error }] = useMutation(TEST1); const updateFormState = (key, value) => { setFormState(prev => ({ ...prev, [key]: value })); }; const handleSubmit = async (e) => { e.preventDefault(); try { await createMitgliedanmeldung({ variables: { name: formState.name } }); setFormState({ name: '' }); } catch (err) { console.error(err); } }; return ( <div> <form onSubmit={handleSubmit}> <input onChange={e => updateFormState('name', e.target.value)} id="name" value={formState.name} ></input> <button type="submit" disabled={loading}> {loading ? '提交中...' : 'Mitglied werden 1'} </button> {error && <p>提交失败: {error.message}</p>} </form> </div> ) }
4. Apollo Client配置注意事项
- 客户端环境变量需以
NEXT_PUBLIC_开头,否则Next.js客户端无法读取,比如NEXT_PUBLIC_STRAPI_GRAPHQL_URL、NEXT_PUBLIC_STRAPI_TOKEN - Strapi的GraphQL授权头需要
Bearer前缀,否则请求会被拒绝
修改后的Apollo Client配置:
import { ApolloClient, InMemoryCache } from "@apollo/client" const defaultOptions = { query: { fetchPolicy: "no-cache", }, } const client = new ApolloClient({ uri: process.env.NEXT_PUBLIC_STRAPI_GRAPHQL_URL, headers: { "Authorization": `Bearer ${process.env.NEXT_PUBLIC_STRAPI_TOKEN}` }, cache: new InMemoryCache(), defaultOptions, }); export default client
依赖优化
可移除@apollo/react-hooks,因为@apollo/client已包含所有钩子,无需单独安装。
内容的提问来源于stack exchange,提问作者O'SAMP
相关产品推荐
相关产品推荐

