Here I am using server component for Search form but to able to empty the input field when user click the cancel button I import a <SearchReset/>
which is a client component but i cant reset or empty the form.
SearchForm.tsx
;<Form
action="/search"
className="search-form input input-bordered flex items-center gap-2 bg-white py-2 px-4 max-w-md mx-auto rounded border-2"
>
<input
name="query"
defaultValue={query}
className="search-input grow w-full focus:outline-none outline-none focus:ring-0 active:ring-0"
placeholder="Seacrh Ideas"
/>
{query ? (
<SearchReset />
) : (
<button type="submit" className="flex items-center">
<Search className="text-secondary size-6" />
</button>
)}
</Form>
SearchReset.tsx
export default function SearchReset () {
const reset = () => {
const form = document.querySelector(".search-form") as HTMLFormElement
console.log(form)
if (form) {
const input = form.querySelector(
'input[name="query"]',
) as HTMLInputElement
console.log(input) // this works
if (input) {
input.value = "" // this doesnt
}
form.reset()
}
}
return (
<button type="reset" className="flex items-center" onClick={reset}>
<X className="text-black-200 size-4" />
</button>
)
}
I tried to access the form’s input field after I click the reset button which I can but when am trying to set it’s value empty or reset the form it’s not working
2
Answers
There are two states that you want to change here.
/search?query=something
to/search
.You can do the first by keeping the form a server component, because the state you’re changing is outside the component itself.
But for the second one you can’t.
This isn’t possible with server components. as a thumb rule. whenever you want to update the state of a server component, then it means it has to be converted to a client component. So, your
<SearchForm />
component will have to become a client component by using the'use client'
directive. After you do that, you’ll no longer need all of those tricky things to get around it, like using querySelectors in your<SearchReset />
component.It’s not a bad thing to make a client component! it’s a normal thing that happens all the time, usually forms are almost always client components due to their intensive reactivity.
for example some people like to make validation on the fly, some folks format the currencies, some people use react-hook-form so it’s completely normal to have almost all your forms in your website as client components, for myself I never had a complete server form component, everything around the form is usually static, but the form itself is almost always a client component.
For anything else, you keep them server components, only when you have an interactive part, you make that small part a client component. But in your case this isn’t the case, because not only the button is a reactive component, also the input field as well.
since almost everything inside the
<Form>
is gonna become a client components, then it would be so much weird to have the<Form>
alone a server component. So, move your Form to a separate file and make it a client component, for the page, keep your pages always server components.This is the easiest solution and everyone do this.
Here’s how this would look like after the modifications:
File: src/app/search/page.tsx
File: src/components/search-form.tsx
In your code you reset
searchStr
to ”, but you didn’t resetquery
value. That is probably the issue