diff --git a/src/App.js b/src/App.js index f2c5ebe..117a53e 100644 --- a/src/App.js +++ b/src/App.js @@ -9,27 +9,45 @@ class App extends Component { componentDidMount() { console.log('fetch items') fetch('/.netlify/functions/todos-read-all') - .then((response) => { - console.log(response) - return response.json() - }) - .then((myJson) => { - console.log(myJson) - this.setState({ - todos: myJson - }) + .then((response) => { + console.log(response) + return response.json() + }) + .then((myJson) => { + console.log(myJson) + this.setState({ + todos: myJson }) + }) + } + logState = () => { + console.log(this.state) } saveTodo = (e) => { e.preventDefault(); + const { todos } = this.state + const todoValue = this.inputElement.value - if (!this.inputElement.value) { + if (!todoValue) { alert('Please add todo text') return false } + + // Optimistically add todo to UI + const temporaryValue = { + data: { + title: todoValue + } + } + const optimisticTodoState = todos.concat(temporaryValue) + this.setState({ + todos: optimisticTodoState + }) + + // Make API request to create new todo fetch('/.netlify/functions/todos-create', { body: JSON.stringify({ - title: this.inputElement.value + title: todoValue }), method: 'POST', // mode: 'cors', // no-cors, cors, *same-origin @@ -37,13 +55,46 @@ class App extends Component { .then(response => response.json()) .then((json) => { console.log(json) + // remove temporaryValue from state and persist API response + const persistedState = removeOptimisticTodo(todos).concat(json) + // Set persisted value to state + this.setState({ + todos: persistedState + }) + // fin }).catch((e) => { - console.log('errrrr', e) + console.log('An API error occurred', e) + const revertedState = removeOptimisticTodo(todos) + // Reset to original state + this.setState({ + todos: revertedState + }) }) } deleteTodo = (e) => { + const { todos } = this.state const todoId = e.target.dataset.id console.log(`Delete todo ${todoId}`) + // Optimistically remove todo from UI + const filteredTodos = todos.reduce((acc, current) => { + const currentId = getTodoId(current) + if (currentId === todoId) { + // save item being removed for rollback + acc.rollbackTodo = current + return acc + } + // filter deleted todo out of the todos list + acc.optimisticState = acc.optimisticState.concat(current) + return acc + }, { + rollbackTodo: {}, + optimisticState: [] + }) + + this.setState({ + todos: filteredTodos.optimisticState + }) + // Make API request to delete todo fetch(`/.netlify/functions/todos-delete/${todoId}`, { method: 'POST', }) @@ -51,14 +102,19 @@ class App extends Component { .then((json) => { console.log(json) }).catch((e) => { - console.log('errrrr', e) + console.log(`There was an error removing ${todoId}`, e) + // Add item removed back to list + this.setState({ + todos: filteredTodos.optimisticState.concat(filteredTodos.rollbackTodo) + }) }) } renderTodos() { const { todos } = this.state return todos.map((todo, i) => { - const { data } = todo - const id = todo.ref['@ref'].split('/').pop() + const { data, ref } = todo + const id = getTodoId(todo) + console.log('id', id) return (