Next.js 13+如何获取并渲染数据库数据?
NextJS >=13 数据获取与渲染解决方案
先梳理你代码里的问题
- 加了
"use client"的客户端组件,不能定义成async function,这是第一个报错的核心原因。 "use server"不能放在客户端组件的内部函数里,这个指令只能用在服务器组件的顶层或单独的服务端函数文件中,客户端组件里用它完全无效还会引发问题。- 默认的服务器组件(无
"use client"标识)不能使用useState这类客户端钩子,所以你移除"use client"后会触发第二个错误。
针对不同场景的解决方案
场景1:仅展示数据,无客户端交互(推荐用服务器组件)
服务器组件天然支持async/await,不需要useState和useEffect,直接在组件内获取数据后渲染,全程在服务端完成,性能更优。
// 无需添加"use client",默认是服务器组件 import axios from "axios" async function ProductsComponent() { try { const productsresponse = await axios.get(`${process.env.BASE_URL}/api/productControllers`) if (productsresponse.status !== 200) { console.log("Failed to fetch Products") return <div>加载产品失败</div> } const products = productsresponse.data.message return ( <div className="flex flex-col"> <h3>产品名称</h3> {products?.map(product => ( <div key={product.id}> {/* 必须加key,避免React警告 */} <h4>{product?.productName}</h4> </div> ))} </div> ) } catch (error) { console.error("获取产品出错:", error) return <div>加载产品出错</div> } } export default ProductsComponent
场景2:需要客户端交互(比如过滤、排序)
这类场景必须用客户端组件(加"use client"),但组件本身不能是异步函数,把数据获取逻辑放在useEffect里的异步函数中执行即可。
"use client" import axios from "axios" import { useEffect, useState } from "react" // 组件是普通函数,不能加async function ProductsComponent() { const [products, setProducts] = useState<any[]>([]) const [isLoading, setIsLoading] = useState(true) const [error, setError] = useState<string | null>(null) useEffect(() => { const fetchProducts = async () => { try { const productsresponse = await axios.get(`${process.env.BASE_URL}/api/productControllers`) if (productsresponse.status === 200) { setProducts(productsresponse.data.message) } else { setError("获取产品失败") } } catch (err) { setError("获取产品出错") console.error(err) } finally { setIsLoading(false) } } fetchProducts() }, []) if (isLoading) return <div>正在加载产品...</div> if (error) return <div>{error}</div> return ( <div className="flex flex-col"> <h3>产品名称</h3> {products?.map(product => ( <div key={product.id}> <h4>{product?.productName}</h4> </div> ))} </div> ) } export default ProductsComponent
场景3:兼顾服务端预取数据+客户端交互
先在服务器组件里获取数据,再把数据作为props传给客户端组件,这样既享受服务端渲染的性能,又能在客户端处理交互逻辑。
服务器组件(负责取数据):
// 无需"use client",默认服务器组件 import axios from "axios" import ClientProductsComponent from "./ClientProductsComponent" async function ProductsComponent() { try { const productsresponse = await axios.get(`${process.env.BASE_URL}/api/productControllers`) if (productsresponse.status !== 200) { console.log("Failed to fetch Products") return <div>加载产品失败</div> } const products = productsresponse.data.message // 将数据传给客户端组件 return <ClientProductsComponent products={products} /> } catch (error) { console.error("获取产品出错:", error) return <div>加载产品出错</div> } } export default ProductsComponent
客户端组件(负责交互):
"use client" import { useState } from "react" // 定义产品类型,替代any更规范 interface Product { id: string productName: string } function ClientProductsComponent({ products }: { products: Product[] }) { const [filteredProducts, setFilteredProducts] = useState(products) // 示例:添加产品搜索过滤功能 const handleSearch = (keyword: string) => { const result = products.filter(p => p.productName.includes(keyword)) setFilteredProducts(result) } return ( <div className="flex flex-col"> <input type="text" placeholder="搜索产品..." onChange={(e) => handleSearch(e.target.value)} className="mb-4 p-2 border rounded" /> <h3>产品名称</h3> {filteredProducts?.map(product => ( <div key={product.id} className="mb-2"> <h4>{product?.productName}</h4> </div> ))} </div> ) } export default ClientProductsComponent
内容的提问来源于stack exchange,提问作者NewJS
相关产品推荐
相关产品推荐

