When the user clicks the 'Edit' button, the input field opens, allowing the user to type their new task. However, I'm unable to implement saving these changes when the user clicks the 'Save' button. Currently, when the user clicks 'Save,' the previous task is saved, but the new task disappears. In my Task component I created a useState that gets an initial state equal to the current state. I then created onSaveClicked which should change my current task to a new task. When I check with the Redux development tools, I can see that my payload is being updated, but it is not showing up in the UI.
import { ADD_TASK, REMOVE_TASK, UPDATE_TASK } from "../actionsTypes";
import { v4 as uuidv4 } from "uuid";
export const initialState = {
tasklist: [], //tasklist
};
export function taskReducer(state = initialState, action) {
switch (action.type) {
case ADD_TASK:
return {
...state,
tasklist: [
...state.tasklist,
{
id: uuidv4(),
title: action.payload,
isCompleted: false,
isEditing: false,
status: "To do",
number: state.tasklist.length + 1,
},
],
};
case REMOVE_TASK:
return {
...state,
tasklist: state.tasklist.filter((todo) => action.payload !== todo.id),
};
case UPDATE_TASK:
return {
...state,
tasklist: state.tasklist.map((prevTask) =>
prevTask.id === action.payload.id
? { ...prevTask, title: action.payload.newTitle }
: prevTask
),
};
default:
return state;
}
}
import React, { useState } from "react";
import "./Task.css";
import Button from "@mui/material/Button";
import DeleteIcon from "@mui/icons-material/Delete";
import EditIcon from "@mui/icons-material/Edit";
import { useDispatch } from "react-redux";
import { updateTask } from "../../store/actions";
const Task = ({ task, onDelete }) => {
const [isEditing, setIsEditing] = useState(false);
const [inputValue, setInputValue] = useState(task.title);
const dispatch = useDispatch();
const onEdit = () => {
setIsEditing(!isEditing);
};
const onSaveClicked = (title) => {
dispatch(updateTask(title.id, inputValue));
setIsEditing(!isEditing);
};
return (
<li>
{isEditing ? (
<input
id="edittask"
type="text"
value={inputValue}
onChange={(e) => {
// const newName = e.target.value; // setInputValue
// dispatch(updateTask(task.id, newName));
setInputValue(e.target.value);
}}
/>
) : (
<>
{task.number}
<p>{task.title}</p>
{task.isCompleted}
{task.status}
</>
)}
{!isEditing ? (
<Button onClick={onEdit} variant="outlined" endIcon={<EditIcon />}>
Edit
</Button>
) : (
<Button onClick={onSaveClicked} variant="outlined">
Save
</Button>
)}
<Button onClick={onDelete} variant="outlined" endIcon={<DeleteIcon />}>
Remove
</Button>
</li>
);
};
export default Task;
import { ADD_TASK, REMOVE_TASK, UPDATE_TASK } from "./actionsTypes";
export const addTask = (title) => ({
type: ADD_TASK,
payload: title, //title
});
export const removeTask = (id) => ({
type: REMOVE_TASK,
payload: id,
});
export const updateTask = (id, title) => ({
type: UPDATE_TASK,
payload: { id, newName: title },
});
import React from "react";
import InputTask from "../InputTask/InputTask";
import HeaderOfTaskList from "../HeaderOfTaskList/HeaderOfTaskList";
import Task from "../Task/Task";
import { useDispatch, useSelector } from "react-redux";
import { removeTask, addTask } from "../../../redux/store/actions";
import "./TaskList.css";
export const TaskList = () => {
const dispatch = useDispatch();
const task = useSelector((state) => state.tasklist);
const handleDelete = (id) => {
dispatch(removeTask(id));
};
const handleAddTask = (tasklist) => {
dispatch(addTask(tasklist));
};
return (
<div>
<InputTask addTask={handleAddTask} />
<HeaderOfTaskList />
<ul>
{task.map((task) => (
<Task
task={task}
key={task.id}
onDelete={() => handleDelete(task.id)}
/>
))}
</ul>
</div>
);
};
I have the above snippets of code
The issue it would seem is that you are accessing an id
property of the button
element's onClick
event object and not the specific task
object you are trying to update the title of.
const onSaveClicked = (title) => { // <-- title is onClick event object
dispatch(updateTask(title.id, inputValue));
setIsEditing(!isEditing);
};
...
<Button onClick={onSaveClicked} variant="outlined">
Save
</Button>
You can access the current task
prop value that is closed over in scope:
const Task = ({ task, onDelete }) => {
...
const onSaveClicked = () => {
dispatch(updateTask(task.id, inputValue));
setIsEditing(!isEditing);
};
...
<Button onClick={onSaveClicked} variant="outlined">
Save
</Button>
...
};
You could also explicitly pass the task
reference to the onSaveClicked
callback:
const Task = ({ task, onDelete }) => {
...
const onSaveClicked = (task) => {
dispatch(updateTask(task.id, inputValue));
setIsEditing(!isEditing);
};
...
<Button onClick={() => onSaveClicked(task)} variant="outlined">
Save
</Button>
...
};