Next.js中页面作为组件引用时getServerSideProps/getStaticProps不执行怎么办
问题原因
Next.js 中getServerSideProps是仅页面级组件生效的特殊生命周期函数:
- 当你直接访问
/pageb路由时,Next.js 会识别PageB是路由对应的页面组件,自动执行其内部的getServerSideProps方法,拿到返回的data作为props传入PageB组件,因此可以正常渲染数据。 - 当你在PageA中把PageB作为普通子组件引入时,Next.js 不会执行PageB的
getServerSideProps方法,因此没有data参数传入PageB,组件内部默认值为空数组,所以展示空列表。
解决方案
方案1:抽离公共请求逻辑,在父页面的getServerSideProps中统一请求数据
- 先把PageB的接口请求逻辑抽成公共函数:
// 可以放在单独的utils/api.ts文件里 export const fetchPageBData = async () => { const myData = await axios.get(`http://localhost:443/api/data`); return myData.data; }
- 修改PageA的
getServerSideProps,同时请求两个接口的数据,把PageB需要的data通过props传入子组件:
import type { NextPage } from 'next'; import axios from 'axios'; import PageB from '../pageb'; import { fetchPageBData } from 'utils/api'; const PageA: NextPage = ({ chats, pageBData }: any) => { return ( <> <div> <table style={{ width: "100%" }}> <thead> <tr style={{ width: "100%" }}> <th style={{ width: "50%" }}>Sender Id</th> </tr> </thead> <tbody> { chats.map((chat: any) => { return <tr key={chat._id}> <td>{chat.sender_id}</td> </tr>; }) } </tbody> </table> </div> {/* 把请求到的data传给PageB */} <PageB data={pageBData}></PageB> </> ) } export const getServerSideProps = async ({ query }) => { const chatsRes = await axios.get(`http://localhost:443/api/chats`); // 同时请求PageB需要的数据 const pageBData = await fetchPageBData(); return { props: { chats: chatsRes.data, pageBData: pageBData } }; } export default PageA;
方案2:将PageB的数据请求改为客户端侧请求
如果PageB不需要服务端渲染数据,可以把请求逻辑放到组件内部的useEffect中执行,这样不管是作为页面还是子组件都能正常获取数据:
import type { NextPage } from 'next'; import axios from 'axios'; import { useEffect, useState } from 'react'; const PageB: NextPage = ({ data: propsData }: any) => { const [data, setData] = useState(propsData || []); // 组件挂载后自动请求数据 useEffect(() => { const fetchData = async () => { const res = await axios.get(`http://localhost:443/api/data`); setData(res.data); } // 如果父组件传了数据就用父组件的,否则自己请求 if (!propsData) { fetchData(); } }, [propsData]) return ( <div> <table style={{ width: "100%" }}> <thead> <tr style={{ width: "100%" }}> <th style={{ width: "20%" }}>Name</th> </tr> </thead> <tbody> { data.map((post: any) => { return <tr key={post._id}> <td>{post.name}</td> </tr>; }) } </tbody> </table> </div> ) } export default PageB;
内容的提问来源于stack exchange,提问作者Code Guru
相关产品推荐
相关产品推荐

