useDispatch: Creating and Deleting Tasks with Redux
useDispatch returns the Redux store's dispatch function. Use it to trigger createTask and deleteTask from the Tasks component, and add a utility function to format dates for display.
The task list renders from Redux state. The UI sees the data. What does not work yet: the Save and Delete buttons have no effect on the store.
useDispatch is the hook that connects button clicks to Redux actions.
Importing useDispatch
import { useDispatch } from 'react-redux';
const dispatch = useDispatch();Call useDispatch() once at the top of the component. It returns the store's dispatch function. Every dispatch(actionCreator(...)) call flows to the reducer.
Also import the action creators from the barrel file we created:
import actions from '../../actions';Local State for the Form
The task form needs two input values: task title and date/time. These belong in local useState, not Redux. They are needed only inside Tasks while the form is open.
const [taskTitle, setTaskTitle] = useState('');
const [dateTime, setDateTime] = useState('');Bind both to their inputs with value and onChange:
<input
type="text"
value={taskTitle}
onChange={(e) => setTaskTitle(e.target.value)}
/>
<input
type="datetime-local"
value={dateTime}
onChange={(e) => setDateTime(e.target.value)}
/>When to use Redux vs useState: if a piece of state is only needed by one component and no other component will ever read it, keep it in useState. Text input values while typing are a classic example. The finished task object, once saved, belongs in Redux so it can be read from anywhere.
Dispatching CREATE_TASK
Update onSaveClick to dispatch the action:
function onSaveClick() {
const newTask = {
id: Math.floor(Math.random() * 1_000_000),
taskTitle,
dateTime,
};
dispatch(actions.createTask(newTask));
setTaskTitle('');
setDateTime('');
setIsNewTaskOpen(false);
}Math.floor(Math.random() * 1_000_000) generates a random integer id. In a production app that talks to a database, the server generates the id. This local approach is for development only.
After dispatch, both input fields reset to empty and the form closes. The component re-renders because useSelector detects the new task in the store.
Dispatching DELETE_TASK
Add an onDeleteClick handler and wire it to the delete button:
function onDeleteClick(task) {
if (window.confirm('Delete this task?')) {
dispatch(actions.deleteTask(task.id));
}
}In the task list, pass the current task to the handler:
<button
className="icon-button"
onClick={() => onDeleteClick(task)}
>
×
</button>The action creator receives the task id, returns { type: DELETE_TASK, payload: taskId }, and the reducer filters it out of state. The task disappears from the list immediately.
Formatting Dates for Display
Raw datetime-local values display as 2026-07-01T09:00, which is not readable. Create a utility function in src/utils/index.js:
export function toDisplayDateFormat(dateString) {
const date = new Date(dateString);
const day = date.getDate();
const month = date.toLocaleString('default', { month: 'short' });
const year = date.getFullYear();
const hours = date.getHours().toString().padStart(2, '0');
const mins = date.getMinutes().toString().padStart(2, '0');
return `${day} ${month} ${year}, ${hours}:${mins}`;
}Import it in Tasks.js and use it while rendering:
import { toDisplayDateFormat } from '../../utils';
// inside the task map:
<div className="task-subtitle">{toDisplayDateFormat(task.dateTime)}</div>The utils/ folder exists for exactly this reason: reusable logic that belongs to no single component.
ExpanduseDispatch triggering action creators that flow through the reducer to update the store
The Essentials
useDispatch()returns the store's dispatch function. Call it once at the top of the component. Pass action objects created by action creators to it.- Form input state stays in
useState.taskTitleanddateTimeare local to the Tasks component during input. Once saved, the structured task object moves into Redux state via dispatch. - The
utils/folder handles reusable logic. Date formatting has no business in a component. Extracting it toutils/index.jskeeps components focused on rendering.
Further Reading and Watching
- useDispatch API docs: official reference
- JavaScript Date object: MDN reference for the date formatting methods used in the utility
components/tasks/Tasks.json GitHub: full component with useSelector, useDispatch, form state, search filter, and loading/error statesutils/index.json GitHub: thetoDisplayDateFormatutility function
Practice what you just read.
Keep reading