Reputation: 55293
PersonsFetcher
is a server component that fetches data from an API then passes that to a client component to present the data interactively (filtering, sorting, etc). The other elements, Button
and PersonModal
(has a form to create a new person), don't need fetched data to work, so I placed them outside of PersonsFetcher
.
'use client';
import { Button } from '@/components/ui/button';
import { ListPlus } from 'lucide-react';
import PersonModal from '@/components/PersonModal';
import { useState } from 'react';
import PersonsFetcher from '@/components/PersonsFetcher';
export default function PersonsPage() {
const [isModalOpen, setIsModalOpen] = useState(false);
return (
<>
<Button onClick={() => setIsModalOpen(true)}>
<ListPlus className="mr-2 h-4 w-4" /> Add new resource
</Button>
<Suspense fallback={<div>Loading...</div>}>
<PersonsFetcher />;
</Suspense>
<PersonModal
isOpen={isModalOpen}
setIsOpen={setIsModalOpen}
/>
</>
);
}
As you can see, 'use client'
will make <PersonsFetcher>
a client component (therefore, producing an error in Next.js). But I need 'use client'
in order to use useState
.
How to solve this dilemma?
Upvotes: 1
Views: 203
Reputation: 3502
Not totally sure if this works or if it so its the right approach at all tbh 🤞 ... how about a new client component with its own state for button and modal and then a new server component to render both of these client component and the server component PersonsFetcher
we had ..
New client component (as it can be standalone to render inside server comp):
'use client';
import { Button } from '@/components/ui/button';
import { ListPlus } from 'lucide-react';
import PersonModal from '@/components/PersonModal';
import { useState } from 'react';
export default function PersonsFormModal() {
const [isModalOpen, setIsModalOpen] = useState(false);
return (
<>
<Button onClick={() => setIsModalOpen(true)}>
<ListPlus className="mr-2 h-4 w-4" /> Add new resource
</Button>
<PersonModal
isOpen={isModalOpen}
setIsOpen={setIsModalOpen}
/>
</>
);
}
and a New server component to render them (since server comp can render the client but not vice versa)
import PersonsFetcher from '@/components/PersonsFetcher';
import PersonsFormModal from '..';
export default function PersonsPage() {
return (
<>
<PersonsFormModal/>
<Suspense fallback={<div>Loading...</div>}>
<PersonsFetcher />;
</Suspense>
</>
);
}
Upvotes: 1