-
Notifications
You must be signed in to change notification settings - Fork 1
Add frontend for search #46
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: 01-11-demo_97ac36a2_add_server_api
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| import React, { useEffect, useState } from 'react'; | ||
|
|
||
| const TaskSearch = () => { | ||
| const [tasks, setTasks] = useState([]); | ||
| const [loading, setLoading] = useState(true); | ||
| const [error, setError] = useState(null); | ||
| const [searchQuery, setSearchQuery] = useState(''); | ||
|
|
||
| useEffect(() => { | ||
| setLoading(true); | ||
| fetch(`/search?query=${encodeURIComponent(searchQuery)}`) | ||
| .then(response => { | ||
| if (!response.ok) { | ||
| throw new Error('Network response was not ok'); | ||
| } | ||
| return response.json(); | ||
| }) | ||
| .then(data => { | ||
| setTasks(data); | ||
| setLoading(false); | ||
| }) | ||
| .catch(error => { | ||
| setError(error.message); | ||
| setLoading(false); | ||
| }); | ||
| }, [searchQuery]); // Depend on searchQuery | ||
|
Comment on lines
+9
to
+26
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The current data fetching logic is susceptible to race conditions. If a user types quickly, multiple requests are sent, but there's no guarantee responses will arrive in the same order. This could result in older data overwriting newer data in the UI. To prevent this, you should cancel the previous request when a new one is initiated. The standard approach in React is to use an useEffect(() => {
const controller = new AbortController();
setLoading(true);
fetch(`/search?query=${encodeURIComponent(searchQuery)}`, { signal: controller.signal })
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json();
})
.then(data => {
setTasks(data);
setLoading(false);
})
.catch(error => {
if (error.name !== 'AbortError') {
setError(error.message);
setLoading(false);
}
});
return () => {
controller.abort();
};
}, [searchQuery]); // Depend on searchQuery |
||
|
|
||
| if (loading) { | ||
| return <div>Loading...</div>; | ||
| } | ||
|
|
||
| if (error) { | ||
| return <div>Error: {error}</div>; | ||
| } | ||
|
|
||
| return ( | ||
| <div> | ||
| <h2>Task Search</h2> | ||
| <input | ||
| type="text" | ||
| placeholder="Search tasks..." | ||
| value={searchQuery} | ||
| onChange={(e) => setSearchQuery(e.target.value)} | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The current implementation triggers a search API call on every keystroke because |
||
| /> | ||
| <ul> | ||
| {tasks.map(task => ( | ||
| <li key={task.id}> | ||
| <p>{task.description}</p> | ||
| </li> | ||
| ))} | ||
| </ul> | ||
| </div> | ||
| ); | ||
| }; | ||
|
|
||
| export default TaskSearch; | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code assumes that the
datareceived from the API is always an array. If the API returns something else (e.g.,nullor an error object with a 200 status code), the call totasks.mapon line 46 will throw an error and crash the component. It's safer to validate the data before setting the state to ensure it's an array.