Create your first React app - Part 4 (Adding and deleting users)
In order to add new users, we'll start by updating the handleAddUser() function in the root component so that it looks like this:
const handleAddUser = (evt) => {
setSelectedUserId(0);
}
Remember that the handleAddUser() function will be triggered when the button in the root component is clicked. By setting the selectedUserId to 0, it indicates that a new user is being created (0 is not a valid user id, but the data access component will generate a valid id when we insert it into the database - we'll see that soon).
Run the app, and notice that now when you click on the 'Add User' button, the UserForm will be displayed with all of it's text inputs empty. The selectedUserId state is used a the userId prop that is passed into the user form. So when this prop changes, the UserForm will re-render. After it renders, the callback that we passed into useEffect() will not trigger getUserById() on the data access component, because the userId is 0. This will leave the state variables in UserForm at their default values (which are all initialized to empty strings).
Now, we'll need to update the handleUserSaved() function in the root component. Recall that this function will be triggered in the submit handler of the UserForm (because it gets passed to the UserForm as the onUserSaved prop). The handleUserSaved() function currenlty assumes that we are always updating users, but now we'll add some logic so that it can determine whether to do an update or an insert. Modify the function so that it looks like this:
const handleUserSaved = (updatedUser) => {
if(updatedUser.id > 0){
uda.updateUser(updatedUser);
setUsers(users.map(u => u.id === updatedUser.id ? updatedUser : u))
}else{
uda.insertUser(updatedUser);
setUsers([...users, updatedUser])
}
// hide the user form
setSelectedUserId(-1);
}
If the id of the updatedUser parameter is greater than 0, then we call updateUser() on the data access component, otherwise, we call insertUser(). After the user is inserted, we need to change the 'users' state, so we pass in a new array when we call setUsers(). This array consists of a copy of the 'users' state/array and the updatedUser.
If you run the app now, you should be able to add new users.
Deleting users
In this step well add a 'Delete' button to the UserForm. But before we do that, we need to declare another prop, which well call onUserDeleted. Remember that the 'users' state is declared in the root component. So all changes to users should happen in the root component. So we'll define a function that deletes a user, and pass that into the UserForm as the onUserDelete prop.
Add a new prop to the UserForm() function by updating it's first line to look like this:
function UserForm({userId, onUserSaved, onUserDeleted}){
Next, add this function to the root component (put it just befoe the return statement):
const handleUserDeleted = (id) => {
// delete the user from the database
uda.deleteUser(id);
// update the 'users' state
setUsers(users.filter(user => user.id !== id));
// hide the user form
setSelectedUserId(-1);
}
Now we'll pass this function to the UserForm as the onUserDeleted prop. Update the JSX returned by the RootCompnent so that it looks like this:
<div>
<h1>User Manager</h1>
<button onClick={handleAddUser}>Add User</button>
<p>Number of users: {users.length}</p>
<UserList users={users} onUserSelected={handleUserSelected} />
{selectedUserId > -1 && <UserForm key={selectedUserId} userId={selectedUserId} onUserSaved={handleUserSaved} onUserDeleted={handleUserDeleted} />}
</div>
We've added an 'onUserDeleted' prop to the UserForm element, and set it's value to the handleUserDeleted function (this line of code is getting long and ugly, we can discuss different ways of formatting this code in class).
Now we'll add a 'Delete' button to the UserForm, but we only want to display it when the userId prop is greater than 0. So we'll use 'conditional rendering'. Add this code to the JSX in the UserForm (put it just after the submit button):
{userId > 0 && <input type="button" value="Delete" onClick={() => {onUserDeleted(userId)}} />}
We've added an 'onClick' attribute that triggers an anonymous function. Inside the anonyomous function, we trigger onUserDeleted prop/function (we wrapped the call to onUserDeleted() in an anonymous function so that we could pass a parameter into it - we can discuss this in class).
If you run the app now, you should be able to delete users.
And that you've created your first CRUD application in React, I'm assuming that we'll have many things to discuss in our next class meeting!