Search code examples
reactjsreact-hooksgraphqlcrud

Edit item in react with graphql


I want to create a crud app with react and grapgql(my problem is for update section). I have a list of todos and when I click on edit button it is gone to edit page.

problem: I want to see the todo title when I go to edit page (but it doesn't show todo title in the field.it's just show an empty input field) and then after editing item navigate to home page. Thank you for your help

my components:

Todos.js:

const Todos = () => {
  const { data, loading, error } = useQuery(GET_TODOS);

  if (loading) return <p>Loading ... </p>
  if (error) return <p>Something went wrong!</p>

  return (
    <>
      {!loading && !error && (
        <div>
          {data.todos.map(todo => (
            <Todo todo={todo} key={todo.id}/>
          ))}
        </div>
      )}
    </>
  );

Todo.js:

const Todo = ({ todo }) => {

  const navigate = useNavigate();
  return (
    <div>
      <button  onClick={() => navigate(`/edit/${todo.id}`)}>
        Edit
      </button>
    </div>
 )

EditTodo.js:

  const [title, setTitle] = useState("")
  const { id } = useParams();

  const { data } = useQuery(GET_TODO, {
    variables: { id }
  });

  const [editTodo] = useMutation(EDIT_TODO, {
    variables: { id },
    refetchQueries: [{ query: GET_TODOS, variables: { id } }]
  })


  const handleSubmit = (e) => {
    e.preventDefault();
     editTodo(title);
    // navigate('/')
  }

  return (
    <>
    
      {data.todo.title}
      <form onSubmit={handleSubmit}>
        <div>
          <div>
            <input
              value={title}
              onChange={(e) => setTitle(e.target.value)}
              required
              type="text" placeholder="Name" />
          </div>
          <div >
            <button>
              Edit
            </button>
          </div>
        </div>
      </form>
    </>
  );

Queries & mutatation:

const GET_TODOS = gql`
  query getTodos {
   todos{
     id
     title
    }
  }
`;

const GET_TODO = gql`
  query getTodo($id:ID!){
    todo(id:$id){
     id 
     title
    }
  }
`;
const EDIT_TODO = gql`
  mutation EditTodo($id: ID! $title: String!) {
    EditTodo(id: $id title: $title) {
      id
      title
    }
  }
`;

Solution

  • I find the solution :adding a useEffect, here is EditTodo.js file

    const EditTodo = () => {
      const { id } = useParams();
      const navigate = useNavigate();
    
      const { data } = useQuery(GET_TODO, {
        variables: { id }
      });
      const [title, setTitle] = useState("")
      
      useEffect(()=>{
        if(data){
          setTitle(data.todo.title || "")
        }
      },[data])
    
    
      const [editTodo] = useMutation(EDIT_TODO, {
        variables: { id, title },
        refetchQueries: [{ query: GET_TODOS, variables: { id } }]
      })
    
    
      const handleSubmit = (e) => {
        e.preventDefault();
        editTodo(title);
        navigate('/')
      }