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

基于WPGraphQL的无头WordPress产品分页问题求助

问题:Next.js集成WPGraphQL实现产品页码分页无效

原本在WordPress中可通过page/2、page/3这类URL实现产品分页,现在在Next.js应用中想要实现相同的页码切换分页(直接跳转至第N页加载对应产品)。但WPGraphQL默认仅支持基于游标的分页,尝试使用wp-graphql-offset-pagination插件注册offsetPagination字段后,修改offset值加载的产品始终一致。

当前代码情况

Next.js查询代码

export const useProductsData = () => {
  const params = useParams()
  const { handle } = params;

  const [products, setProducts] = useState([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  const fetchProductsData = async () => {
    const query = gql`
    query {
      products(where: { categoryIn: "${handle}", stockStatus: IN_STOCK }, first: 25) {
        nodes {
          id
          sku
          slug
          status
          name
          image {
            sourceUrl
          }
          ... on SimpleProduct {
            id
            name
            price
          }
          ... on VariableProduct {
            id
            name
            price
          }
        }
      }
    }
  `;

    try {
      const result = await fetchWooCommerceData(query);
      setProducts(result.products.nodes);
      setLoading(false);
    } catch (error) {
      setError(error);
      setLoading(false);
    }
  };

  fetchProductsData();

  return { products, loading, error };
};

注册offsetPagination字段的PHP代码

// Register offsetPagination fields for WooCommerce products
register_graphql_field(
    'RootQueryToProductConnectionWhereArgs',
    'offsetPagination',
    [
        'type' => 'OffsetPagination',
        'description' => 'Paginate products with offsets',
    ]
);

测试查询与输出

query Products {
  products(where: { offsetPagination: { size: 10, offset: 30 } }) {
    pageInfo {
      offsetPagination {
        hasMore
        hasPrevious
        total
      }
    }
    nodes {
      id
      name
      # Other product fields
    }
  }
}

查询输出:

{
  "data": {
    "products": {
      "pageInfo": {
        "offsetPagination": {
          "hasMore": true,
          "hasPrevious": true,
          "total": 16300
        }
      },
      "nodes": [
        // 产品列表始终相同
      ]
    }
  }
}

解决方案

1. 修复offsetPagination参数的映射逻辑

仅注册字段不足以让参数生效,需要将offsetPagination的参数映射到WooCommerce的产品查询逻辑中。替换原注册代码为:

add_action( 'graphql_register_types', function() {
    // 为产品连接添加offset分页参数映射
    add_filter( 'graphql_product_connection_query_args', function( $query_args, $source, $args, $context, $info ) {
        if ( isset( $args['where']['offsetPagination'] ) ) {
            $pagination = $args['where']['offsetPagination'];
            // 传递offset参数到查询
            if ( isset( $pagination['offset'] ) ) {
                $query_args['offset'] = $pagination['offset'];
            }
            // 传递每页数量参数到查询
            if ( isset( $pagination['size'] ) ) {
                $query_args['posts_per_page'] = $pagination['size'];
            }
        }
        return $query_args;
    }, 10, 5 );

    // 注册offsetPagination到where参数
    register_graphql_field(
        'RootQueryToProductConnectionWhereArgs',
        'offsetPagination',
        [
            'type' => 'OffsetPagination',
            'description' => 'Paginate products with offsets',
        ]
    );
} );

2. 修改Next.js查询代码,支持动态页码

  • 从URL参数获取当前页码,计算对应的offset值
  • 使用GraphQL变量传递参数(避免字符串拼接风险)
  • 监听页码和分类变化,自动重新查询
import { useEffect, useState } from 'react';
import { useParams } from 'next/navigation';
import gql from 'graphql-tag';

export const useProductsData = () => {
  const params = useParams()
  const { handle, page = 1 } = params; // 默认页码为1
  const pageSize = 25;
  const offset = (parseInt(page) - 1) * pageSize; // 计算偏移量:(页码-1)*每页数量

  const [products, setProducts] = useState([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  const fetchProductsData = async () => {
    const query = gql`
    query GetProducts($category: String!, $offset: Int!, $pageSize: Int!) {
      products(where: { 
        categoryIn: $category, 
        stockStatus: IN_STOCK,
        offsetPagination: { offset: $offset, size: $pageSize }
      }) {
        pageInfo {
          offsetPagination {
            hasMore
            hasPrevious
            total
          }
        }
        nodes {
          id
          sku
          slug
          status
          name
          image {
            sourceUrl
          }
          ... on SimpleProduct {
            price
          }
          ... on VariableProduct {
            price
          }
        }
      }
    }
  `;

    try {
      const result = await fetchWooCommerceData(query, {
        variables: {
          category: handle,
          offset: offset,
          pageSize: pageSize
        }
      });
      setProducts(result.products.nodes);
      setLoading(false);
    } catch (error) {
      setError(error);
      setLoading(false);
    }
  };

  // 监听分类和页码变化,重新获取数据
  useEffect(() => {
    setLoading(true);
    fetchProductsData();
  }, [handle, page]);

  return { products, loading, error };
};

3. 固定排序规则避免结果重复

如果分页结果仍有重复,可在查询中添加固定的排序条件,确保每次查询的产品顺序一致:

query GetProducts($category: String!, $offset: Int!, $pageSize: Int!) {
  products(where: { 
    categoryIn: $category, 
    stockStatus: IN_STOCK,
    offsetPagination: { offset: $offset, size: $pageSize },
    orderby: { field: DATE, order: DESC } // 按发布时间倒序
  }) {
    // ... 其他字段
  }
}

内容的提问来源于stack exchange,提问作者Sylwester Zabielski

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 03:17:06