You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用表单(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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 17:05:43