NextJS app router: Client component with data fetching, inside a suspense boundary gets statically rendered

I have a reproduction for this issue here.

I’m playing around with NextJS app router, and Suspense.

I have two implementations of a simple client component that fetches data with React Query. One uses useSuspenseQuery the other uses a regular query.

export function TodosRq() {

    const query = useQuery<Array<{id: number, title: string}>>({ queryKey: ['todos'], queryFn: async () => {

        await new Promise((res) => setTimeout(res, 10000));
        const res = await  fetch("https://jsonplaceholder.typicode.com/todos")
        return res.json();
    } })


    return <div>
        {query.data?.map((v) => {
            return <div> 
                RQ
                {v.id} {v.title}
            </div>
        })}
    </div>

}
export function TodosRqSuspense() {

    const query = useSuspenseQuery<Array<{id: number, title: string}>>({ queryKey: ['todos'], queryFn: async () => {

        await new Promise((res) => setTimeout(res, 10000));
        const res = await  fetch("https://jsonplaceholder.typicode.com/todos")
        return res.json();
    } })


    return <div>
        {query.data.map((v) => {
            return <div> 
                RQ
                {v.id} {v.title}
            </div>
        })}
    </div>

}

In my App router page, I can render either of these components:

      {/* nb. this suspense boundary won't do anything */}
      <Suspense fallback={'rq loading'}>
        <h2>Todos RQ</h2>
        <TodosRq/>
      </Suspense>

or

      <Suspense fallback={'rq loading'}>
        <h2>Todos RQ</h2>
        <TodosRqSuspense/>
      </Suspense>

Intuitively, what I’m expecting here is that server render will render application in it’s loading state, stream that to the client, and then the client takes over and makes the API call.

However, what I actually observe, is that in the case of using the suspense query, actually NextJS applies static rendering to TodosRqSuspense component. That is, in a production build, it returns prerendered HTML, never making the 10 second wait.

It’s important to observe both the behaviour of the dev server, as well as the production build.

Dev Server Production Build
TodosRq We don’t see the suspense boundary. We wait 10 seconds till content appears. Content does not appear in the root document. We don’t see the suspense boundary. We wait 10 seconds till content appears. Content does not appear in the root document.
TodosRqSuspense We see the suspense boundary. We wait 10 seconds till content appears. Content appears in the root document. (The dev server appears to do something funny where it can modify the response body of the network request) We get the content immediately. Content is in the root document.

What am I missing here?

Here’s the relevant parts of the documentation and how I understand it:

Static vs Dynamic rendering – for server components default behaviour is that all content will statically rendered (that is, rendered at build time), even if it involves data fetching, unless it fits into one of the exceptions, such as using the cookies or connection methods.

Client components – Client components are pre-rendered on the server, (first render on the server), and but then when they hit the client then the work is done on the client.

Suspense – Allows the ‘first render’ to show all the loading skeletons etc, and then if using RSCs then they’ll stream in, and, this is where I am having some misunderstanding, I would have thought that client components would still do their data fetching client side, and then display when they are complete.

What NextJS recommends – NextJS recommend that you do your data fetching in server components, just to be clear. However – within the context of some kind of migration, it makes sense that we might keep some things as client components. In any case, I’m trying to understand the nuance here.

nb. if we add useSearchParams to our client component, then this behaviour does not occur and behaves inline with how I’ve intuited.

2

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật