混合组件模式
在构建 next.js 应用程序时,您需要区分代码应该编造在服务端还是客户端。
服务端组件和客户端组件的使用时机
场景 | 服务端 | 客户端 |
---|---|---|
请求接口 | ✅ | ❌ |
操作node api | ✅ | ❌ |
访问浏览器 api | ❌ | ✅ |
使用react hooks | ❌ | ✅ |
使用react class components | ❌ | ✅ |
混合使用
import { useState } from 'react'
import { Carousel } from 'acme-carousel'
export default function Gallery() {
let [isOpen, setIsOpen] = useState(false)
return (
<div>
<button onClick={() => setIsOpen(true)}>View pictures</button>
{isOpen && <Carousel />}
</div>
)
}
上述的代码其实会报错,因为默认情况下,所有的组件都是服务端组件,由于服务端组件不能使用react hooks, 所以会报错。 因此我们需要对此进行改造
- Gallery
- Carousel
import CarouselComponent from './CarouselComponent';
export default function Gallery() {
return (
<div>
<CarouselComponent />
</div>
)
}
"use client"
import { useState } from 'react'
import { Carousel } from 'acme-carousel'
export default function CarouselComponent() {
const [isOpen, setIsOpen] = useState(false)
return (
<>
<button onClick={() => setIsOpen(true)}>View pictures</button>
{isOpen && <Carousel />}
</>
)
}
上述的改造中,其实就是一种服务端组件嵌套客户端组件的模式,这种方式是允许的,相反客户端组件嵌套服务端组件不被允许。
'use client'
import ServerComponent from './Server-Component'
export default function ClientComponent({ children }) {
const [count, setCount] = useState(0)
return (
<>
<button onClick={() => setCount(count + 1)}>{count}</button>
<ServerComponent />
</>
)
}
上述代码中,ServerComponent
是服务端组件,因此不能在客户端组件中引入,所以会报错。
我们也可以通过插槽的方式,将服务端组件嵌套在客户端组件中,这种方式是允许的。
- client-component
- server-component
'use client'
import { useState } from 'react'
export default function ClientComponent({ children }) {
const [count, setCount] = useState(0)
return (
<>
<button onClick={() => setCount(count + 1)}>{count}</button>
{children}
</>
)
}
import ClientComponent from './client-component'
import ServerComponent from './server-component'
export default function Page() {
return (
<ClientComponent>
<ServerComponent />
</ClientComponent>
)
}