NextJS 14 SSR - 在初始渲染后添加到列表客户端

问题描述 投票:0回答:1

我是 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> 
   </>
 



reactjs next.js
1个回答
0
投票

这里有一些问题。

首先,您不需要

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> 
   </>
 )}

© www.soinside.com 2019 - 2024. All rights reserved.