redwoodjs / example-todo

Example Todo app written with Redwood
95 stars 28 forks source link

Add edit todo mutation and input #73

Closed ryanmearns closed 1 year ago

ryanmearns commented 2 years ago

The problem this PR intends to solve is that the todos should be able to be edited after they have been created.

To solve this, this PR uses the renameTodo mutation created in the SDL in the TodoListCell to update the Todo body with the following:

const UPDATE_TODO_BODY = gql`
  mutation TodoListCell_RenameTodo($id: Int!, $body: String!) {
    renameTodo(id: $id, body: $body) {
      id
      __typename
      body
    }
  }
`

It also performs an optimistic update with the following handler:

  const handleSaveClick = (id, body) => {
    updateTodoBody({
      variables: { id, body },
      optimisticResponse: {
        __typename: 'Mutation',
        updateTodoBody: { __typename: 'Todo', id, status: 'loading' },
      },
    })
  }

To execute the mutation the PR adds an input field that can be toggled on in the TodoItem

const TodoItem = ({ id, body, status, onClickCheck, onClickSave }) => {

  const [editTodo, setEditTodo] = useState(false)
  const [newTodo, setNewTodo] = useState(body)
  const inputRef = useRef()

  const handleSave = () => {
    onClickSave(id, newTodo)
    setEditTodo(false)
  }

  useEffect(() => {
    if (editTodo) {
      inputRef.current.focus()
    }
  }, [editTodo])

// Omited

  return (
      <SC.Item>
        <SC.Target onClick={handleCheck}>
          <Check type={status} />
        </SC.Target>
        <SC.Body>
          {!editTodo ? (
            <Todo />
          ) : (
            <>
              <SC.Input
                type="text"
                ref={inputRef}
                value={newTodo}
                onChange={(e) => {
                  setNewTodo(e.target.value)
                }}
              />
              <SC.Button type="submit" value="Save Item" onClick={handleSave} />
            </>
          )}
        </SC.Body>
      </SC.Item>
    )
}