I’m trying to realize very simple functionality. A user must have a possibility to search posts by its tag. So, I have the following Feed.jsx component:
"use client";
import { useState, useEffect } from "react";
import PostCard from "./PostCard";
const PostCardList = ({ data, handleTagClick }) => {
return (
<div className='mt-16 prompt_layout'>
{data.map((post) => (
<PostCard
key={post._id}
post={post}
handleTagClick={handleTagClick}
/>
))}
</div>
);
};
const Feed = () => {
const [posts, setPosts] = useState([]);
// Search states
const [searchText, setSearchText] = useState("");
const fetchPosts = async () => {
console.log(`searchText: ${searchText}`);
let url = '/api/post';
if (searchText) {
url = `/api/post/tag/${searchText}`;
}
const response = await fetch(url);
const data = await response.json();
setPosts(data);
};
useEffect(() => {
fetchPosts();
}, []);
const handleSearchChange = (e) => {
setSearchText(e.target.value);
if (e.key === "Enter") {
fetchPosts();
}
};
return (
<section className='feed'>
<form className='relative w-full flex-center'>
<input
type='text'
placeholder='Search for a tag or a username'
value={searchText}
onChange={handleSearchChange}
required
className='search_input peer'
/>
</form>
<PostCardList
data={posts}
handleTagClick={() => {}}
/>
</section>
);
};
export default Feed;
But it doesn’t work. When a user types tag into input and hits Enter, /api/post
endpoint invoked instead of /api/post/tag/${searchText}
. Console writes the following lines:
searchText:
searchText:
ChatGPT suggests that the reason why the /api/post
endpoint is always being invoked instead of /api/post/tag/${searchText}
when the user hits Enter is because the searchText
variable is updated asynchronously. By the time fetchPosts()
is called within handleSearchChange()
, the searchText
value hasn’t been updated yet.
To fix this issue, it modified my code as follows:
const fetchPosts = async (searchQuery) => {
console.log(`searchQuery: ${searchQuery}`);
console.log(`searchText: ${searchText}`);
let url = '/api/post';
if (searchQuery) {
url = `/api/post/tag/${searchQuery}`;
}
const response = await fetch(url);
const data = await response.json();
setPosts(data);
};
useEffect(() => {
fetchPosts();
}, []);
const handleSearchChange = (e) => {
setSearchText(e.target.value);
if (e.key === "Enter") {
fetchPosts(e.target.value);
}
};
But it doesn’t help. Console writes the following:
searchQuery: undefined
searchText:
searchQuery: undefined
searchText:
2
Answers
From docs, onChange is not triggered until the element looses focus.
I suggest using different event such as
onKeyPress
,onKeyDown
,onKeyUp
, etc.Try this:
remove this block from handleSearchChange function:
Then, add this onSubmit handler to the form:
If didn’t work, make sure the API URL you’re requesting is valid