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

Next.js中使用React Server Components触发ReactServerComponentsError问题求助

Next.js中使用React Server Components触发ReactServerComponentsError问题求助

问题描述

我在Next.js项目中使用React Server Components时遇到了编译错误,具体报错信息如下:

Failed to compile
./src\app\components\projects\slider.js
ReactServerComponentsError:
You're importing a component that needs useEffect. It only works in a Client Component but none of its parents are marked with "use client", so they're Server Components by default.

,-[C:\Users\elias\Documents\Trabalhos\Repositorios\portifolio\src\app\components\projects\slider.js:1:1]
1 | /* @jsxImportSource @react */
2 | import Image from "next/image";
3 | import "./slider.scss";
4 | import React, { useState, useEffect } from "react";
: ^^^^^^^^^
5 | import dynamic from "next/dynamic";
6 | import "owl.carousel/dist/assets/owl.carousel.css";
7 | import "owl.carousel/dist/assets/owl.theme.default.css";
`----

Maybe one of these should be marked as a client entry with "use client":
./src\app\components\projects\slider.js
./src\app\page.tsx

我已经尝试给父组件page.tsx加上/* @jsxImportSource @react */,但还是报错,怀疑是不是项目没配置Babel导致的?

代码概要

slider.js 文件

/* @jsxImportSource @react */
import Image from "next/image";
import "./slider.scss";
import React, { useState, useEffect } from "react";
import dynamic from "next/dynamic";
import "owl.carousel/dist/assets/owl.carousel.css";
import "owl.carousel/dist/assets/owl.theme.default.css";

let productsp = [
  {
    id: 1,
    name: "Product Number 1",
    brand: "Brand Name",
    url: "products-number-1",
    price: 100,
  },
  // 省略重复的产品数据
];

var $ = require("jquery");

if (typeof window !== "undefined") {
  window.$ = window.jQuery = require("jquery");
}

const OwlCarousel = dynamic(() => import("react-owl-carousel"), {
  ssr: false,
});

const Slider = () => {
  const options = {
    margin: 30,
    responsiveClass: true,
    nav: true,
    dots: true,
    autoplay: false,
    smartSpeed: 1000,
    navClass: ["owl-prev", "owl-next"],
    navText: ['', ''],
    responsive: {
      0: { items: 1 },
      400: { items: 1 },
      600: { items: 2 },
      700: { items: 3 },
      1000: { items: 4 },
    },
  };

  return (
    <div className="row no-gutters">
      <div
        className="col-xl-12 col-lg-12 col-md-12 col-sm-12 col-12 mt-3 pb-2 bg-white"
        id="owl-carousel-products"
      >
        <h3 className="text-center">
          <span className="heading float-left w-100">Featured Products</span>
        </h3>
        <ul id="owl-carousel-ul" className="owl-carousel owl-loaded owl-drag">
          <OwlCarousel
            className="owl-theme"
            loop
            margin={4}
            nav={true}
            navText={[
              '<img src="/images/Arrow_left.png" />',
              '<img src="/images/Arrow_right.png" />',
            ]}
            dots={false}
            animateIn={true}
            {...options}
          >
            {productsp && productsp.length > 0
              ? productsp.map((product) => (
                  <div
                    id="featuredProducts"
                    className="item float-left w-100"
                    key={product.name}
                  >
                    <div className="productListing col-lg-5th col-md-4 col-sm-6 col-xs-12">
                      <a href={product.url}>
                        <a className="product float-left">
                          <span className="image text-center">
                            <Image
                              id={"img" + product.id}
                              src="images/product.jpg"
                              alt={product.name}
                              title={product.name}
                            />
                          </span>
                          <span className="w-100 text-center mt-1 ">
                            <h5 className="brand text-capitalize float-left">
                              {product.brand}
                            </h5>
                            <span className="name">{product.name}</span>
                            <strong className="itemPrice p-0">
                              Price: {product.price}
                            </strong>
                          </span>
                        </a>
                      </a>
                    </div>
                  </div>
                ))
              : ""}
          </OwlCarousel>
        </ul>
      </div>
    </div>
  );
};

export default Slider;

page.tsx 文件

import { Experience } from './components/experience/experience'
import { Header } from './components/header/header'
import { Info } from './components/information/information'
import Slider from './components/projects/slider'
import "./styles/home.scss"
import { EmailIcon } from './components/icons/email-icon'
import { SocialBtns } from './components/social-btns/social-btns'

export default function Home() {
  return (
    <main className="container">
      <Header />
      <Experience />
      <Info />
      <div className="buttons">
        <SocialBtns />
        <a className="btn-primary" href="mailto:elias.souza.es609@gmail.com">
          contact me
          <EmailIcon />
        </a>
      </div>
      <Slider />
    </main>
  )
}

解决方案

别担心,这个问题和Babel完全没关系!Next.js已经内置了处理React Server Components的所有工具,不需要额外配置Babel。

错误的核心原因是:Next.js 13+的App Router默认所有组件都是Server Components,而useState、useEffect这类React客户端钩子,以及依赖浏览器环境的库(比如jQuery、owl-carousel)只能在Client Components里运行。你之前加的/* @jsxImportSource @react */是用来指定JSX编译源的,和标记Client Component完全不相关,所以没用。

正确的做法很简单:

  • 在**slider.js文件的最顶部**添加"use client";指令,这个指令必须放在所有import语句之前,告诉Next.js这个组件是Client Component:
"use client";
/* @jsxImportSource @react */
import Image from "next/image";
import "./slider.scss";
import React, { useState, useEffect } from "react";
// 后续代码保持不变

不需要给page.tsx加这个指令(除非你想把整个页面都变成Client Component),我们只需要把实际用到客户端逻辑的Slider组件标记为Client Component就好,这样其他组件还能保留Server Component的优势(比如服务器端渲染、减少客户端JS体积)。

另外,你的Slider组件里还用到了jQuery和react-owl-carousel,这些都依赖浏览器的window对象,只有在Client Component里才能正常运行,所以标记"use client"是必须的。

备注:内容来源于stack exchange,提问作者Elias Souza

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.21 12:53:03