We’ll use fetch and refactor our client-side task completion logic to send an update to the server, and update the UI with a success message once the save has completed successfully.
[00:00] We're loading our todos from the JSON server and we're adding new items to the server. But if we toggle a todo, that change won't be reflected on the server.
[00:07] To save changes to existing todos, we'll need to create a new function that makes a put request to the server. This will look very similar to the existing create todo function, so we'll start by duplicating that. I'm going to select create todo, make a copy, and I'm going to rename this Save todo.
[00:28] The first big difference here is that our URL's going to be slightly different. I'm going to wrap this in back ticks, and I'm going to use string interpolation to append our todo ID to the base URL. This is going to be our base URL/ are passed in todo.id.
[00:49] The next thing we have to change is we have to go from making a post request to a put request. This function will do a put to our base URL/ our todos ID, it'll pass in the application/json headers, it'll pass our todo as the body of the request, and then will return a promise that's already called .json on the response.
[01:11] I'll save this in an app.js, I'm going to update my import here to also import Save todo. Then we can scroll down and find our handle toggle method, and we'll do some refactoring.
[01:24] In the current code, we define a pipeline that takes in an ID and our current list of todos and returns a new list that includes our update. In order to send this update along to the server, we're going to need to break this out a bit, so we can grab that toggle todo.
[01:38] Let's start by pulling apart the pipeline we currently have defined. I'll start by defining a function, I'm going to call get toggle todo, and that's going to be my pipeline minus the third function. I'm just going to cut this, paste it back in. Now we're going to pipe find by ID to toggle todo.
[01:57] Now I can use this to get the updated item. I'll define const updated and I'm going to set that to equal a call to get toggle todo. I'm going to pass in my ID, followed by this.state.todos.
[02:12] Now get updated todos, it's just going to equal the partial application of update todo with this.state.todos, which gives us a function that just needs an updated item. We'll pass updated in there.
[02:24] Then our this.setState call doesn't have to change, and now we can call Save todo with our updated item. Then we'll call .then to handle the response, and we'll just show a temporary error message using this.ShowTempMessage and we'll pass in todo updated.
[02:49] I'll save this, we'll let the browser reload. Now when I check items off, we'll see that we get our todo updated message. If we open up db.json, we'll see that more of our items have been set to complete.
Scott,
You can, you just need to make a few small changes. Just keep in mind that json-server is file based, so it isn't something I'd use beyond an example.
json-server
as a project dependency with npm i -S json-server
todoService.js
file to const baseUrl = './todos'
package.json
file to: "start": "json-server db.json --static ./build"
Then run now
and you'll have a running example like [https://todoreact-umhsjinwdh.now.sh/](this one).
You may also want to reserve the original start script for local development by renaming it to something like dev
- leaving "dev": "react-scripts start",
in your package.json
in addition to the new start
script.
Hope this helps.
Hi Andrew,
I completed video 23 and my code is exactly the same as yours. The only difference is that I am using NodeJS version 7.10.0. I have both the json server going and the webpack dev server while working on everything so that is not the issue. I think Babel is not reading the code correctly. It has to do with updating the todos. I get all other messages that we have created, like addTodo message, and error message when text has not been applied to the unput before hitting return. So after I completed the code in video 23 and then went to check off a todo (not delete it, but ONLY check it as complete), this is what I got in the Chrome JS DevTools console:
Uncaught TypeError: Cannot read property 'isComplete' of undefined at toggleTodo (bundle.js:33981) at bundle.js:33665 at App._this.handleToggle (bundle.js:32909) at Object.executeOnChange (bundle.js:24778) at ReactDOMComponent._handleChange (bundle.js:24593) at Object.ReactErrorUtils.invokeGuardedCallback (bundle.js:17193) at executeDispatch (bundle.js:16976) at Object.executeDispatchesInOrder (bundle.js:16999) at executeDispatchesAndRelease (bundle.js:16387) at executeDispatchesAndReleaseTopLevel (bundle.js:16398)
Uncaught TypeError: Cannot read property 'isComplete' of undefined at toggleTodo (todoHelpers.js:8) at utils.js:3 at App._this.handleToggle (App.js:35) at Object.executeOnChange (LinkedValueUtils.js:132) at ReactDOMComponent._handleChange (ReactDOMInput.js:239) at Object.ReactErrorUtils.invokeGuardedCallback (ReactErrorUtils.js:69) at executeDispatch (EventPluginUtils.js:85) at Object.executeDispatchesInOrder (EventPluginUtils.js:108) at executeDispatchesAndRelease (EventPluginHub.js:43) at executeDispatchesAndReleaseTopLevel (EventPluginHub.js:54)
This is the code it's referring to in todoHelpers.js:
export const toggleTodo = (todo) => ({...todo, isComplete: !todo.isComplete})
This is where the error is occurring in bundle.js:
var toggleTodo = exports.toggleTodo = function toggleTodo(todo) { return Object.assign({}, todo, { isComplete: !todo.isComplete }); };
from todoHelpers.js line 8:
export const toggleTodo = (todo) => ({...todo, isComplete: !todo.isComplete})
in utils.js:
const _pipe = (f, g) => (...args) => g(f(...args))
I can only imagine that it is a transpiling error because I checked against your code and we have the same code. I may be missing something, but I haven't come across any difference yet, Here is the link to my code on github:
https://github.com/interglobalmedia/todo-list-create-react-app
Thanks!
Maria,
I'm not able to pull this code down and run it right now, but this might be the issue:
https://github.com/interglobalmedia/todo-list-create-react-app/blob/master/src/components/todo/TodoItem.js#L10
You've defined the partially applied handleToggle
function: const handleToggle = partial(props.handleToggle, props.id)
but you are using the props.handleToggle
function in the onChange
for the checkbox. Try removing props.
from that and just pass in the locally created handleToggle
that is partially applied with the id. Without it, the event object is being passed as the first argument to that function and it's trying to use that as the id
to find the appropriate item in the list.
Hope this clears it up for you.
Had one issue with this otherwise great less that POST
should be a PUT
If i want to deploy this as an example to now.sh say, can I use json-server? Or is there another service I could hook up to it?