我是 NextJS 14 的新手,请询问任何知道如何在从服务器组件获取后添加到列表的人。基本上我希望将其他项目添加到当前列表中。我已经有一个客户端组件,它具有“使用客户端”,并且从从 mongo db 调用的服务器组件中解析了道具。但我不知道更新客户端组件上的列表的最佳实践是什么。我已经尝试使用 props 和使用 setState 的单独状态进行以下操作。虽然它有效,但对我来说它看起来像是一个黑客。 (jobs 是来自服务器的初始数据解析道具。)出于 SEO 原因和速度,我希望保留初始渲染)
// server comp
const jobResults = await getPagedJobsData(query)
return (
<HomePage data={jobResults}/>
)
}
// HomePage client component
const Home = ({data}) => {
const {jobs} = data
//const jobs = []
const [initialRender, setInitialRender] = useState(false)
const [jobData, setJobData] = useState(null)
const didMount = useRef(false);
const [count, setCount] = useState(1)
useEffect(()=> {
setInitialRender(true)
setJobData(jobs)
}, [])
useEffect(() => {
// Return early, if this is the first render:
if ( ! didMount.current ) {
return ()=> didMount.current = true;
}
// Paste code to be executed on subsequent renders:
let query = {
page_num: count,
title: '',
location : '',
contractTypeSel : '',
remoteDays : "Any",
skills: ''
}
const prepare = async () => {
let t = await getPagedJobsData(query)
const addtionalJobs = t.jobs
setJobData([...jobData, ...addtionalJobs])
}
prepare()
}, [count]);
const handlePageClick = () => {
setCount(count + 1)
}
return (
<>
<div className='border'>
<div>
<div className=''>
{
initialRender == false ? jobs.map((item, index)=> {
return <div key={index}>{item.company}</div>
})
: jobData.map((item, index)=> {
return <div key={index}>{item.company}</div>
})
}
</div>
</div>
</div>
<div className=' items-center'>
<button onClick={handlePageClick}>More</button>
</div>
</>
这里有一些问题。
首先,您不需要
useEffect
钩子来使用传入的数据设置状态。您可以将其更改为:
const Home = ({data}) => {
const {jobs} = data
//const jobs = []
const [initialRender, setInitialRender] = useState(false)
const [jobData, setJobData] = useState(jobs) // Just insert them as the initial state here.
const didMount = useRef(false);
const [count, setCount] = useState(1)
useEffect(()=> {
setInitialRender(true)
}, [])
其次,您很可能希望将第二个
useEffect
挂钩和异步函数移至服务器组件中,然后将按钮移至客户端组件中。 Next 13+ 迫使开发人员习惯的一大变化是,您可能会拥有几个“真正”的小组件,这样它们就可以在客户端上渲染,而大多数组件在服务器上渲染.
不要使用 state 来存储页面数据,而是使用 searchParams ,它会自动传递到页面组件中,然后将 onClick
方法更改为 href 并使用 Next.js
Link
组件。如果您这样做,您甚至根本不需要上面提到的客户端组件。总而言之,最终看起来像这样:const Home = ({searchParams: {
page,
// showAll - Look below. Whichever works best with what you're trying to accomplish.
}})
let query = {
page_num: count, // Apply some logic here to use the page or showAll param.
title: '',
location : '',
contractTypeSel : '',
remoteDays : "Any",
skills: ''
}
const jobs = await getPagedJobsData(query)
return (
<HomePage data={jobResults}/>
)
}
// HomePage client component -- Make this a server component now!
const Home = ({data}) => {
const {jobs} = data
return (
<>
<div className='border'>
<div>
<div className=''>
{
initialRender == false ? jobs.map((item, index)=> {
return <div key={index}>{item.company}</div>
})
: jobData.map((item, index)=> {
return <div key={index}>{item.company}</div>
})
}
</div>
</div>
</div>
<div className='items-center'>
<Link
href={`/somePage?page=${currentPage + 1}`}
// href={`/somePage?showAll=true`} Whichever fits your use case.
>More</Link>
</div>
</>
)}