Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions graphite-demo/frontend.jsx
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);
})
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Error state not cleared after successful fetch

Medium Severity

When a fetch succeeds, the success handler sets tasks and loading but never resets error to null. If a previous request failed and set an error, all subsequent successful requests will still display the error screen because the if (error) check on line 32 returns early with the stale error message.

Fix in Cursor Fix in Web

.catch(error => {
setError(error.message);
setLoading(false);
});
}, [searchQuery]); // Depend on searchQuery
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Race condition with out-of-order API responses

Medium Severity

Each keystroke triggers a new API call without canceling previous requests. If responses return out of order (e.g., a slow response for "a" arrives after a fast response for "ab"), stale results overwrite the correct ones, causing the displayed tasks to not match the current searchQuery.

Fix in Cursor Fix in Web


if (loading) {
return <div>Loading...</div>;
}

if (error) {
return <div>Error: {error}</div>;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Error state hides input, preventing user recovery

Medium Severity

When an error occurs, the early return on line 32-34 renders only the error message and completely hides the search input. Since the input is hidden, users cannot modify searchQuery to trigger a new fetch attempt. The component becomes permanently stuck in the error state with no recovery path for the user other than remounting the entire component.

Fix in Cursor Fix in Web


return (
<div>
<h2>Task Search</h2>
<input
type="text"
placeholder="Search tasks..."
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
/>
<ul>
{tasks.map(task => (
<li key={task.id}>
<p>{task.description}</p>
</li>
))}
</ul>
</div>
);
};

export default TaskSearch;
Loading