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

Next.js集成Pusher Presence Channel报错:Invalid user data求助

在Next.js中使用Pusher遇到"Invalid user data: 'presence-channel'"错误

我正在练习在Next.js中使用Pusher,遇到报错:Error: Invalid user data: 'presence-channel',多次尝试仍无法解决。以下是相关代码文件:

api/index.js 文件

import { pusher } from "../../../lib/pusher";

// presence channel handler
export default async function handler(req, res) {
  const { message, username } = req.body;
  // trigger a new post event via pusher
  await pusher.trigger("presence-channel", "chat-update", {
    message,
    username,
  });

  res.json({ status: 200 });
}

api/pusher/auth 文件

import { pusher } from "../../../../lib";

export default async function handler(req, res) {
  const { socket_id, channel_name, username } = req.body;

  const randomString = Math.random().toString(36).slice(2);

  const presenceData = {
    user_id: randomString,
    user_info: {
      username,
    },
  };

  try {
    var auth = pusher.authenticateUser(socket_id, channel_name, presenceData);
    res.send(auth);
  } catch (error) {
    console.error(error);
  }
}

lib/index.js 文件

import Pusher from "pusher";

export const pusher = new Pusher({
  appId: process.env.NEXT_PUBLIC_PUSHER_APP_ID,
  key: process.env.NEXT_PUBLIC_PUSHER_KEY,
  secret: process.env.NEXT_PUBLIC_PUSHER_SECRET,
  cluster: process.env.NEXT_PUBLIC_PUSHER_CLUSTER,
  useTLS: true,
});

pages/chat.js 文件

import { useState, useEffect } from "react";
import Pusher from "pusher-js";
import axios from "axios";

export default function Chat({ username }) {
  const [message, setMessage] = useState("");
  const [displayMessage, setDisplayMessage] = useState([]);
  const [onlineUserCount, setOnlineUserCount] = useState(0);

  console.log(process.env.NEXT_PUBLIC_PUSHER_APP_ID);

  const pusher = new Pusher(process.env.NEXT_PUBLIC_PUSHER_KEY, {
    cluster: "ap2",
    authEndpoint: `api/pusher/auth`,
    auth: { params: { username } },
  });

  useEffect(() => {
    const channel = pusher.subscribe("presence-channel");

    channel.bind("pusher:subscription_succeeded", (members) => {
      setOnlineUserCount(members.count);
    });

    channel.bind("pusher:member_added", (member) => {
      setOnlineUserCount(channel.member.count);

      setOnlineUserCount((prevState) => {
        [...prevState, { username: member.info.username }];
      });
    });

    channel.bind("chat-update", (data) => {
      const { message, username } = data;
      setDisplayMessage((prevState) => {
        [...prevState, { message, username }];
      });
    });

    return () => {
      pusher.unsubscribe("presence-channel");
    };
  }, []);

  const handleSubmit = async (e) => {
    e.preventDefault();
    await axios.post("/api/pusher/chat-update", {
      message,
      username,
    });
  };

  return (
    <div>
      {username}
      {displayMessage.map((chat, id) => {
        return <div key={id}>{chat.message}</div>;
      })}

      <form onSubmit={handleSubmit}>
        <input
          type="text"
          onChange={(e) => setMessage(e.target.value)}
          placeholder="Enter Message"
        />
      </form>
    </div>
  );
}

pages/index.js 文件

import Head from "next/head";

export default function Home({ handleLoginChange, handleLogin }) {
  return (
    <div>
      <Head>
        <title>Dealer</title>
        <meta name="description" content="Generated by create next app" />
        <link rel="icon" href="/favicon.ico" />
      </Head>

      <div>
        <form onSubmit={handleLogin}>
          <input
            type="text"
            placeholder="enter your username"
            onChange={handleLoginChange}
          />
          <button>Login</button>
        </form>
      </div>
    </div>
  );
}

_app.js 文件

import "../styles/globals.css";
import { useState } from "react";
import { useRouter } from "next/router";

function MyApp({ Component, pageProps }) {
  const [username, setUsername] = useState("");
  const router = useRouter();

  const handleLogin = (e) => {
    e.preventDefault();
    router.push("/chat");
  };

  return (
    <Component
      handleLoginChange={(e) => setUsername(e.target.value)}
      username={username}
      handleLogin={handleLogin}
      {...pageProps}
    />
  );
}

export default MyApp;

问题分析与解决方案

这个错误的核心是Pusher服务端认证方法使用错误,加上前后端的细节疏漏,逐一修正如下:

1. 修正服务端认证方法

对于Presence频道,Pusher服务端正确的认证方法是authenticate(),而非authenticateUser()。修改api/pusher/auth文件:

import { pusher } from "../../../../lib";

export default async function handler(req, res) {
  const { socket_id, channel_name, username } = req.body;

  const randomString = Math.random().toString(36).slice(2);

  const presenceData = {
    user_id: randomString,
    user_info: {
      username,
    },
  };

  try {
    // 替换为正确的authenticate方法
    const auth = pusher.authenticate(socket_id, channel_name, presenceData);
    res.send(auth);
  } catch (error) {
    console.error(error);
    res.status(500).json({ error: error.message });
  }
}

2. 修复前端依赖与状态更新逻辑

  • 在pages/chat.js的useEffect中,添加pusher和username到依赖数组,确保组件能正确响应变量变化:
useEffect(() => {
  const channel = pusher.subscribe("presence-channel");

  // 其余bind逻辑保持不变

  return () => {
    pusher.unsubscribe("presence-channel");
  };
}, [pusher, username]); // 添加依赖
  • 修正状态更新的返回逻辑,确保状态能正确更新:
// 修正pusher:member_added中的状态更新
channel.bind("pusher:member_added", (member) => {
  // 注意是channel.members.count,不是channel.member.count
  setOnlineUserCount(channel.members.count);
});

// 修正chat-update中的状态更新
channel.bind("chat-update", (data) => {
  const { message, username } = data;
  setDisplayMessage((prevState) => {
    return [...prevState, { message, username }]; // 返回新数组
  });
});

3. 修正API请求路径

chat.js中提交消息的API路径与实际文件路径不匹配,修改为:

const handleSubmit = async (e) => {
  e.preventDefault();
  await axios.post("/api", {
    message,
    username,
  });
};

4. 统一环境变量配置

避免硬编码cluster,保持前后端环境变量一致:

const pusher = new Pusher(process.env.NEXT_PUBLIC_PUSHER_KEY, {
  cluster: process.env.NEXT_PUBLIC_PUSHER_CLUSTER,
  authEndpoint: `/api/pusher/auth`, // 加上斜杠避免路径问题
  auth: { params: { username } },
});

完成以上修改后,重启应用即可解决该错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 23:09:24