Please checkout and subscribe to my video content on YouTube. Feel free to leave comments and suggestions for what content you would like to see.
YouTube Channel
Overview
Simple application with a list of things and the ability to add, edit and delete things. We will use the useReducer hook to manage the state of the array of things.
We will use the useState hook to manage the state of the modal dialog we are using to input the information for the thing we are editing or updating and we use the useState hook to manage the state of the input field in the modal dialog.
Lets Start with the useReducer API
// useThings.js
// --
import React from "react";
const useThings = () => {
// handle the specific action dispatched
const reducer = (state, action) => {
switch (action.type) {
case "ADD_THING": { }
case "DELETE_THING": { }
case "EDIT_THING": { };
default: {
return state;
}
}
};
// here we set things up to use the reducer
const [state, dispatch] = React.useReducer(reducer, {
things: []
});
// the function returns everything needed to the caller to
// dispatch specific action and get the updated state changes
return {
state,
dispatch
};
};
export default useThings;
Modify values in the state
Add An Item: Add the action.data to the end of the array, set state properties
case "ADD_THING": {
return { ...state, things: [...state.things, action.data] };
}
Deleting An Item: Add the action.index slice the array to get the things before the thing specified by the index and everything after the item specified by the index. This in turn is used to create new array which we set state.things with
case "DELETE_THING": {
return {
...state,
things: [
...state.things.slice(0, action.index),
...state.things.slice(action.index + 1)
]
};
}
Editing An Item: Add the action.index slice the array to get the things before the thing specified by the index and everything after the item specified by the index. Next we use the action.data as the new element to replace the element that was previously there. This in turn is used to create new array which we set state.things with.
case "EDIT_THING": {
return {
...state,
things: [
...state.things.slice(0, action.index),
action.data,
...state.things.slice(action.index + 1)
]
};
}
Displaying a Modal for User Input
Using the useState functionality to manage displaying the modal
dialog for inputting data for new things or editing things. The state has two keys, isVisible and value. isVisible will be set to true to show the dialog and false to hide it. The value property will be set when we are actually editing an object. We will also add an additional property called index when editing a thing so we can find it in the state array to update it.
// ThingsList.js
// --
// using the useState functionality to manage displaying the modal
// dialog for inputting data for new things or editing things
const [modalInfo, setModalInfo] = useState({ isVisible: false, value: "" });
Managing the Input Value Using useState
// ThingEdit.js
// --
const [inputValue, setInputValue] = useState();
How we use this in the render method of the component; when there is an input event in the input element, we update the state with the value entered by the user
<IonInput
value={inputValue}
onInput={e => setInputValue(e.target.value)} />
So when the user is finished in the modal they will click on of two buttons to call the handleClick method
<IonButton onClick={() => handleClick(true)}>Save</IonButton>
<IonButton onClick={() => handleClick(null)}>Cancel</IonButton>
If handleClick is called with a true value, then we need to return the value from the input form which is saved in our state, if the value is passed to handleClick is null, then we just need to exit the function and not return any data
// ThingEdit.js
// --
const handleClick = _save => {
handleFormSubmit({ isVisible: false, value: _save && inputValue });
};
Back in the ThingsList component we need to handle the call from the ThingEdit component to process the data received from the modal.
Get the response from the modal/form so we can update or create a new item. if the _formResponse.value is empty then ignore because the user selected the cancel button.
If there is a _formResponse.value & modalInfo.index has a value, then
edit the item; the modalInfo.index variable tells us which item in t he array to update; if no modalInfo.index then create a new things with the _formResponse.value
// ThingsList.js
// --
const handleFormSubmit = _formResponse => {
if (_formResponse.value) {
modalInfo.index != null
? editEntry(modalInfo.index, _formResponse.value)
: addNewEntry(_formResponse.value);
}
// reset the modalInfo state
setModalInfo({ ...modalInfo, isVisible: false, value: "" });
};
Displaying the List Of Things

Rendering the list of things from the components custom hook, useThings, we mentioned at the start of the post.
// get the function from my custom hook to mange the list
// of things
let { state, dispatch } = useThings();
This give us access to the state object and the state object contains state.things. We loop through the array of values using the Array.map() function
<IonList>
{state.things.map((_thing, _index) => (
<IonItem key={_index}>
<IonLabel className="ion-text-wrap">{_thing}</IonLabel>
<IonButton onClick={() => modalInfoWithEntry(_thing, _index)}>
Edit
</IonButton>
<IonButton color="danger" onClick={() => deleteEntry(_index)}>
Delete
</IonButton>
</IonItem>
))}
</IonList>
We have all of the base function that are wrappers for calling the reducer methods with dispatch
// ThingsList.js
//-
/**
* add entry to the list using `dispatch` from custom hook
*/
const addNewEntry = _data => {
dispatch({ type: "ADD_THING", data: _data });
};
/**
* remove entry from the list using `dispatch` and index in the array
* to call custom hook
* @param {*} _index
*/
const deleteEntry = _index => {
dispatch({ type: "DELETE_THING", index: _index });
};
/**
* update an existing entry in the list based on data
* and the index of the entry
* @param {*} _index
* @param {*} _data
*/
const editEntry = (_index, _data) => {
let payload = { index: _index, data: _data };
dispatch({ type: "EDIT_THING", ...payload });
};
Wrapping It All Up
All of the code for this projects in available to you here in the CodeSandbox.io website listed below.
React hooks with useState and useReducer allows for your whole application to just be functional components who's state can be managed with the hooks api.
Here is a link to a great video to give you some of the reasons why you might want to give hooks a try in your application.

Top comments (0)