skip to Main Content

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
    }
  }
`;

2

Answers


  1. Chosen as BEST ANSWER

    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('/')
      }
    

  2. One issue I see in your code is that you are not setting the initial value of the title state in your EditTodo.js component. You can do this by adding a useEffect hook that sets the title state to the value of data.todo.title when the component mounts or when data.todo.title changes. Refer Below:

    useEffect(() => {
      if (data && data.todo) {
        setTitle(data.todo.title);
      }
    }, [data]);
    

    Above code should set the initial value of the title state to the current todo title, which will then be displayed in the input field.

    To navigate back to the home page after editing a to-do item. You can do this by calling the navigate function after calling editTodo. Refer Below:

    const handleSubmit = (e) => {
      e.preventDefault();
      editTodo({
        variables: {
          id,
          title
        }
      });
      navigate('/');
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search