I trying to put value in url and trying to extract value in search.js with router, but I’m getting this error:
TypeError: Cannot read properties of undefined (reading ‘q’)
<form onSubmit={handleSubmit}>
<input
type="text"
placeholder="Search..."
value={searchValue}
onChange={(e) => setSearchValue(e.target.value)}
class="w-full px-4 py-2 rounded-md text-gray-900"
/>
<button type="submit">Submit</button>
</form>
</div>
const handleSubmit = (event) => {
event.preventDefault(); // Prevent the default form submission
router.push(`../search?q=${encodeURIComponent(searchValue)}`);
};
Search.js:
const Search = () => {
const router = useRouter();
const [searchQuery, setSearchQuery] = useState('');
useEffect(() => {
if (router.isReady) {
setSearchQuery(router.query.q || '');
}
}, [router.isReady, router.query.q]);
if (!router.isReady) {
return <div>Loading...</div>; // Or some loading indicator
}
return (
<div>
<p>Search Query: {searchQuery}</p>
</div>
);
};
export default Search;
3
Answers
It’s a bit of a React anti-pattern to store passed data into local state, just reference the data directly, e.g.:
If
router.query
is potentially undefined then use a guard clause or Optional Chaining operatorIf you must store it locally in state, like if you update it independently of the URL params, the solution is similar.
Also, ensure you are using the Pages router (imported from
"next/router"
) and not the App router (imported from"next/navigation"
).The Pages router should default
router.query
to an empty object{}
and likely not require the checks mentioned above.An alternative may also be to use the useSearchParams hook.
The issue you’re encountering, TypeError: Cannot read properties of undefined (reading ‘q’), suggests that router.query is not defined or does not have the property q when you try to access it. This is a common issue with Next.js when dealing with query parameters and routing.
Here are a few things to check and improve:
Make sure you have imported useRouter from next/router in your Search.js file:
Check the URL Construction:
In your handleSubmit function, ensure the URL is correctly formatted. You might want to use a relative path based on the routing setup. In most cases, ../search might not be necessary if you are already on the right route. It could simply be /search:
Ensure Correct Component Rendering:
Make sure that the Search component is correctly being rendered when navigating to /search. Sometimes issues arise if the route is not correctly matched.
Check for router.isReady:
Ensure router.isReady is properly used. If router.isReady is false, it may be that the router has not yet finished initializing.
Here’s how you might adjust the Search.js component:
Server-Side Rendering Considerations:
If your component is being server-side rendered, be aware that query parameters might not be immediately available. You might want to handle this situation by checking if router.query.q is available and ensuring the logic correctly accounts for server-side rendering.
Debugging:
Add some debugging statements to verify what values are present:
By following these steps, you should be able to resolve the issue with reading query parameters in your Next.js application.
The useSearchParams hook in Next.js (introduced in Next.js 13 with the App Router) provides a more straightforward way to handle query parameters. This is especially useful when using the App Router with React Server Components. Here’s how you can use useSearchParams in your Search component:
No change is needed here if you are using URL parameters in your navigation:
If you are using the App Router and want to use useSearchParams, update Search.js like this: