React+Apollo实现GraphQL更新/删除Mutation遇问题求助
Hey there! Let's figure out why your update and delete functions aren't working in your React + Apollo Client app. From what you described, the main suspects are either not correctly grabbing the user ID when you click edit/delete or a conflict with react-router that's messing up ID passing. Let's walk through how to troubleshoot and fix this step by step.
1. First: Verify You're Actually Getting the User ID
This is the most common culprit. Let's check a few key spots:
Check the Edit/Delete Button Click Handler
Make sure you're passing the user's ID directly when triggering the action:
// ❌ Bad: No ID passed to the handler <button onClick={handleEdit}>Edit</button> // ✅ Good: Pass the specific user's ID <button onClick={() => handleEdit(user.id)}>Edit</button> <button onClick={() => handleDelete(user.id)}>Delete</button>
Check Route Parameters (If Using react-router)
If you're navigating to an edit page like /users/edit/:id, confirm you're pulling the ID correctly from the route:
import { useParams } from 'react-router-dom'; const EditUserPage = () => { const { id } = useParams(); console.log('User ID from route:', id); // Print this to confirm it's not undefined! // Rest of your component logic... };
Validate Apollo Mutation Variables
Double-check that the ID is actually being passed to your GraphQL mutation:
import { useMutation, gql } from '@apollo/client'; const UPDATE_USER = gql` mutation UpdateUser($id: ID!, $input: UserInput!) { updateUser(id: $id, input: $input) { id name email } } `; const EditUser = () => { const { id } = useParams(); const [updateUser] = useMutation(UPDATE_USER); const handleSave = async (formData) => { try { await updateUser({ variables: { id: id, // Ensure this ID is not null/undefined input: formData } }); } catch (err) { console.error('Update error details:', err); // Log the full error to see what's wrong } }; };
2. Rule Out react-router Conflicts
If your routing setup is off, it can break ID passing entirely:
Confirm Route Configuration
Make sure your dynamic route is defined correctly in your app's route setup:
import { Routes, Route } from 'react-router-dom'; import UsersList from './UsersList'; import EditUser from './EditUser'; function App() { return ( <Routes> <Route path="/users" element={<UsersList />} /> {/* ✅ Dynamic parameter :id is correctly set */} <Route path="/users/edit/:id" element={<EditUser />} /> </Routes> ); }
Check Navigation to Edit Page
When you navigate to the edit page, ensure you're appending the correct ID:
import { useNavigate } from 'react-router-dom'; const UsersList = () => { const navigate = useNavigate(); const goToEditPage = (userId) => { // ✅ Append the user's ID to the route path navigate(`/users/edit/${userId}`); }; return ( <div> {users.map(user => ( <div key={user.id}> {user.name} <button onClick={() => goToEditPage(user.id)}>Edit</button> </div> ))} </div> ); };
3. Validate Your GraphQL Mutation Setup
Make sure your frontend mutation matches what your Express/Mongoose backend expects:
- Confirm your backend schema defines the
idas a required parameter for update/delete:
# Backend schema example type Mutation { updateUser(id: ID!, input: UserInput!): User deleteUser(id: ID!): Boolean }
- Ensure your frontend mutation query uses the exact same parameter names and types.
4. Debug with Console Logs
Add logs at every step to trace the ID's journey:
- Log the user ID when the edit/delete button is clicked
- Log the route parameter ID when the edit page loads
- Log the variables object right before calling the Apollo mutation
- Catch and log any errors from the mutation call—often the error message will tell you exactly if an ID is missing or invalid
Example Working Edit Component
Here's a condensed, verified example of an edit component that ties everything together:
import { useParams, useNavigate } from 'react-router-dom'; import { useQuery, useMutation, gql } from '@apollo/client'; const GET_USER = gql` query GetUser($id: ID!) { user(id: $id) { id name email } } `; const UPDATE_USER = gql` mutation UpdateUser($id: ID!, $name: String!, $email: String!) { updateUser(id: $id, name: $name, email: $email) { id name email } } `; const EditUser = () => { const { id } = useParams(); const navigate = useNavigate(); const { loading, data, error } = useQuery(GET_USER, { variables: { id } }); const [updateUser] = useMutation(UPDATE_USER); if (loading) return <p>Loading user...</p>; if (error) return <p>Error loading user: {error.message}</p>; const handleSubmit = async (e) => { e.preventDefault(); const { name, email } = e.target.elements; try { await updateUser({ variables: { id: id, name: name.value, email: email.value } }); navigate('/users'); // Navigate back to list after successful update } catch (err) { console.error('Update failed:', err.message); } }; return ( <form onSubmit={handleSubmit}> <input type="text" name="name" defaultValue={data.user.name} required /> <input type="email" name="email" defaultValue={data.user.email} required /> <button type="submit">Save Changes</button> </form> ); }; export default EditUser;
内容的提问来源于stack exchange,提问作者sirrus

