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

Next.js14.2.5+React18页面跳转后Poool付费墙不显示问题

Next.js 14 + Poool React Access 付费墙二次进入失效问题解决

现有配置

首页代码(无预取跳转)

import Link from "next/link";
export default async function Home() {
  return (
    <div className="homepage">
      <Link href='/pool' prefetch={false}>进入付费墙页面</Link> <br />
    </div>
  );
}

付费墙页面代码

'use client'
import { 
  AccessContext, 
  Paywall, 
  RestrictedContent } from "@poool/react-access";
import Link from "next/link";
import { useRef } from "react";


export default function Pool() {
  const accessRef = useRef()

  const destroy = () => {
    console.log("ref", accessRef)
    accessRef.current.destroy(accessRef.current.containerRef)
  }

  const recreate = () => {
    console.log("ref", accessRef)
    accessRef.current.recreate()
  }

  return (
    <div className="container">
      <button onClick={destroy}>销毁付费墙</button> <br />
      <button onClick={recreate}>重建付费墙</button> <br />
      <Link href="/" prefetch={false}>返回首页</Link>
      <br />
      <AccessContext
        appId="<你的应用ID>"
        config={{
          debug: true,
          app_name: 'My app',
          cookies_enabled: true,
          content: '[data-poool]',
          mode: 'custom',
          disable_content_height_calculation: true,
          dom_load_timeout: true,
          popover_enabled: true,
          popover_timeout: 500,
        }}>

        <RestrictedContent>
          <div data-poool />
        </RestrictedContent>
        <Paywall ref={accessRef} />
      </AccessContext>
    </div>
  )
}

问题现象

  • 首次从首页跳转至付费墙页面:Poool付费墙初始化正常,「销毁」「重建」按钮功能正常
  • 返回首页再次进入付费墙页面:付费墙不再显示,按钮功能完全失效

已尝试方案(无效)

  • 组件挂载时调用recreate()
  • 组件卸载时调用destroy()

问题原因与解决方法

核心原因

Next.js 14的App Router采用部分 hydration和客户端组件缓存机制,返回首页再进入时,付费墙组件并未完全重新初始化,accessRef指向的实例已失效,导致付费墙无法渲染、按钮方法无响应。

解决方案1:路由监听+生命周期管控

利用usePathname监听路由变化,在页面进入时强制重置实例,卸载时彻底清理资源:

'use client'
import { 
  AccessContext, 
  Paywall, 
  RestrictedContent } from "@poool/react-access";
import Link from "next/link";
import { useRef, useEffect } from "react";
import { usePathname } from 'next/navigation';

export default function Pool() {
  const accessRef = useRef(null);
  const pathname = usePathname();

  useEffect(() => {
    // 页面进入时重置实例
    if (accessRef.current) {
      try {
        accessRef.current.destroy(accessRef.current.containerRef);
      } catch (e) {
        console.warn('销毁旧实例失败:', e);
      }
      accessRef.current.recreate();
    }

    // 组件卸载时清理实例引用
    return () => {
      if (accessRef.current) {
        accessRef.current.destroy(accessRef.current.containerRef);
        accessRef.current = null;
      }
    };
  }, [pathname]);

  const destroy = () => {
    accessRef.current?.destroy(accessRef.current.containerRef);
  };

  const recreate = () => {
    accessRef.current?.recreate();
  };

  return (
    <div className="container">
      <button onClick={destroy}>销毁付费墙</button> <br />
      <button onClick={recreate}>重建付费墙</button> <br />
      <Link href="/" prefetch={false}>返回首页</Link>
      <br />
      <AccessContext
        appId="<你的应用ID>"
        config={{
          debug: true,
          app_name: 'My app',
          cookies_enabled: true,
          content: '[data-poool]',
          mode: 'custom',
          disable_content_height_calculation: true,
          dom_load_timeout: true,
          popover_enabled: true,
          popover_timeout: 500,
        }}>
        <RestrictedContent>
          <div data-poool />
        </RestrictedContent>
        <Paywall ref={accessRef} />
      </AccessContext>
    </div>
  );
}

解决方案2:禁用组件缓存

在付费墙页面顶部添加配置,强制Next.js每次重新渲染组件,避免缓存导致的实例失效:

'use client'
// 强制组件动态渲染,禁用缓存
export const dynamic = 'force-dynamic';

import { 
  AccessContext, 
  Paywall, 
  RestrictedContent } from "@poool/react-access";
// 其余代码保持不变

解决方案3:手动管理实例生命周期

脱离组件ref自动绑定,手动初始化/销毁实例,确保每次进入页面都创建全新实例:

'use client'
import { usePathname } from 'next/navigation';
import { useEffect, useRef } from 'react';
import { init, destroy, recreate } from '@poool/react-access';

export default function Pool() {
  const pathname = usePathname();
  const containerRef = useRef(null);
  const instanceRef = useRef(null);

  useEffect(() => {
    // 初始化全新实例
    instanceRef.current = init({
      appId: '<你的应用ID>',
      config: {
        debug: true,
        app_name: 'My app',
        cookies_enabled: true,
        content: '[data-poool]',
        mode: 'custom',
        disable_content_height_calculation: true,
        dom_load_timeout: true,
        popover_enabled: true,
        popover_timeout: 500,
      },
      container: containerRef.current,
    });

    // 卸载时销毁实例
    return () => {
      instanceRef.current && destroy(instanceRef.current);
      instanceRef.current = null;
    };
  }, [pathname]);

  const handleDestroy = () => {
    instanceRef.current && destroy(instanceRef.current);
  };

  const handleRecreate = () => {
    instanceRef.current && recreate(instanceRef.current);
  };

  return (
    <div className="container">
      <button onClick={handleDestroy}>销毁付费墙</button> <br />
      <button onClick={handleRecreate}>重建付费墙</button> <br />
      <Link href="/" prefetch={false}>返回首页</Link>
      <br />
      <div ref={containerRef}>
        <div data-poool />
      </div>
    </div>
  );
}

内容的提问来源于stack exchange,提问作者Tsvetomir Dimitrov

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 05:34:55