How to avoid only Client components as soon as I need state?
Answered
Orinoco Crocodile posted this in #help-forum
Orinoco CrocodileOP
Hello everyone!
I'm new here and also new to NextJS. I spent a lot of time over the last 2 days reading documentation and step by step I became a better grasp of the most important concepts of NextJS.
However, I ran into the following problem (using the app router approach):
Let's assume I have a
The fetched data has an array of objects, let's say movies.
I read on the official documentation about the composition patterns on how to pass
https://nextjs.org/docs/app/building-your-application/rendering/composition-patterns
Using this approach we can make sure that the
Let's make the example more concrete:
The
I'm new here and also new to NextJS. I spent a lot of time over the last 2 days reading documentation and step by step I became a better grasp of the most important concepts of NextJS.
However, I ran into the following problem (using the app router approach):
Let's assume I have a
Page
. On that page I'm fetching some data server side so that the Page can stay a ServerComponent
.The fetched data has an array of objects, let's say movies.
I read on the official documentation about the composition patterns on how to pass
ServerComponents
to ClientComponents
by passing them as a children prop.https://nextjs.org/docs/app/building-your-application/rendering/composition-patterns
Using this approach we can make sure that the
ServerComponent
stays a ServerComponent
and doesn't need to be changed to a ClientComponent
.Let's make the example more concrete:
// Page component is a ServerComponent
const Page = async () => {
const {
data: { survey },
} = await fetch(...)
return (
<div>
<Controls movieCount={data.movies.length} />
<Movie movie={movie} />
</Controls>
</div>
)
}
The
ControlsComponent
from above looks the following way: // Controls component is a ClientComponent because of useState
interface Props {
children: ReactNode
movieCount: number
}
const Controls = ({ children, movieCount }: Props) => {
const [movieIndex, setMovieIndex] = useState<number>(0)
const goNextMovie =
slideIndex === movieCount - 1
? undefined
: () => setMovieIndex((prevMovieIndex) => prevMovieIndex + 1)
const goPreviousMovie =
slideIndex === 0 ? undefined : () => setMovieIndex((prevMovieIndex) => prevMovieIndex - 1)
return (
<div>
<button disabled={!goPreviousMovie} onClick={goPreviousMovie}>
Previous Movie
</button>
<button disabled={!goNextMovie} onClick={goNextMovie}>
<Next Movie
</button>
</div>
)
}
Answered by Dayo
there's absolutely nothing wrong with using client components. if you need interactivity then you most likely will need one.
think of client components as the regular components in previous versions of Nextjs. they still get SSR'd
think of client components as the regular components in previous versions of Nextjs. they still get SSR'd
5 Replies
Orinoco CrocodileOP
As you can see, all the
However, now I want to use that index in order to render the
Because from my understanding there is no way of passing the value of the state to the parent component, since you always just pass props down, not up and if you want to change parent components you pass a callback. I cannot define the callback on the parent
But if I don't follow the composition pattern from the documentation and just embed the
I just really want to make sure that this is true, because that would leave so many questions to me on why SSR is so valuable in NextJS. I couldn't really imagine a web app that doesn't use at least some state or interactivity based on some data somewhere higher up in the Components tree.
Controls
component does is having a state with the current index, two functions to increase and decrease the current index and then two buttons which trigger those functions.However, now I want to use that index in order to render the
Movie
component from above that is embedded in the Controls
component. Basically, I want to access the index, get the correct Movie from the fetched data and pass it to the Movie
component. The thing is, is this actually possible without making everything from now on that will use this movieIndex state a ClientComponent
? Because from my understanding there is no way of passing the value of the state to the parent component, since you always just pass props down, not up and if you want to change parent components you pass a callback. I cannot define the callback on the parent
Page Component
though since then that would make the Page already a ClientComponent
.But if I don't follow the composition pattern from the documentation and just embed the
MovieComponent
directly in the ControlsComponent
then that would basically mean from now on every child component of Controls
is a ClientComponent
, correct?I just really want to make sure that this is true, because that would leave so many questions to me on why SSR is so valuable in NextJS. I couldn't really imagine a web app that doesn't use at least some state or interactivity based on some data somewhere higher up in the Components tree.
there's absolutely nothing wrong with using client components. if you need interactivity then you most likely will need one.
think of client components as the regular components in previous versions of Nextjs. they still get SSR'd
think of client components as the regular components in previous versions of Nextjs. they still get SSR'd
Answer
However, now I want to use that index in order to render the Movie component from above that is embedded in the Controls component.
No you can't do this. Everything that is rendered in the server has already been baked into HTML.
The only way you'd consume data from the client is by using another Client Component, or make another request to the server.
So either you press control -> make another server request, or use client component to update the state.
But if I don't follow the composition pattern from the documentation and just embed the MovieComponent directly in the ControlsComponent then that would basically mean from now on every child component of Controls is a ClientComponent, correct?
Yes. This is not a big problem since client component are also prerendered in the server. See @Dayo 's answer.
Orinoco CrocodileOP
Thanks a lot @Alfonsus Ardani and @Dayo ! Really appreciate your help.
I assumed it was that way, I just wasn't sure whether there was a fundamental misunderstanding on my side which could have potentially improved my architecture.
Again, thanks a lot!
I assumed it was that way, I just wasn't sure whether there was a fundamental misunderstanding on my side which could have potentially improved my architecture.
Again, thanks a lot!