make UI snappy
This commit is contained in:
parent
5a0a7e495c
commit
c236cc7ac6
1 changed files with 86 additions and 15 deletions
83
src/App.js
83
src/App.js
|
|
@ -20,16 +20,34 @@ class App extends Component {
|
|||
})
|
||||
})
|
||||
}
|
||||
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 (
|
||||
<div key={i} style={{borderBottom: '1px solid black', padding: 20}}>
|
||||
{data.title} <button data-id={id} onClick={this.deleteTodo}>delete</button>
|
||||
|
|
@ -77,6 +133,7 @@ class App extends Component {
|
|||
Using FaunaDB & netlify functions
|
||||
</p>
|
||||
<div>
|
||||
<button onClick={this.logState}>log state</button>
|
||||
<h2>Create todo</h2>
|
||||
<form className='feature-add' onSubmit={this.saveTodo}>
|
||||
<input placeholder='Todo Info' name='name' ref={el => this.inputElement = el} />
|
||||
|
|
@ -92,4 +149,18 @@ class App extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
function removeOptimisticTodo(todos) {
|
||||
// return all 'real' todos
|
||||
return todos.filter((todo) => {
|
||||
return todo.ref
|
||||
})
|
||||
}
|
||||
|
||||
function getTodoId(todo) {
|
||||
if (!todo.ref) {
|
||||
return null
|
||||
}
|
||||
return todo.ref['@ref'].split('/').pop()
|
||||
}
|
||||
|
||||
export default App
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue