Reputation: 319
I have a to do list app and I store the to do list in a state called list which is an array. When I add a list the component rerender and update the UI but when I console log the list after call the reducer, the list does not update. This is the console. The object before the list is for alert message
And this is my repo link : https://github.com/yustinayasin/tugas-react/tree/day16/day16
Here's my code to add the list in my component:
function App() {
const [kegiatan, setKegiatan] = useState('');
const [isEditing, setIsEditing] = useState(false);
const [editID, setEditID] = useState(null);
const list = useSelector((state) => state.list);
const alert = useSelector((state) => state.alert);
const dispatch = useDispatch();
const handleSubmit = (e) => {
e.preventDefault();
if(!kegiatan) {
dispatch(setAlert({show: true, msg: 'Masukkan kegiatan terlebih dahulu', type: 'danger'}))
} else if (kegiatan && isEditing) {
dispatch(editToList({title: kegiatan, id: editID}));
setKegiatan('');
setEditID(null);
setIsEditing(false);
dispatch(setAlert({show: true, msg: 'Kegiatan berhasil diubah', type: 'success'}));
} else {
console.log('masuk');
dispatch(addToList({title: kegiatan}));
dispatch(setAlert({show: true, msg: 'Kegiatan ditambahkan ke dalam list', type: 'success'}));
console.log(list);
setKegiatan('');
}
}
const clearList = () => {
dispatch(setAlert({show: true, msg: 'List kegiatan kosong', type: 'danger'}));
dispatch(clearAllList());
}
const removeItem = (id) => {
dispatch(setAlert({show: true, msg: 'Kegiatan berhasil dihapus', type: 'danger'}));
dispatch(deleteListItem(), {id: id});
}
const editItem = (id) => {
const specificItem = list.find((item) => item.id === id);
setIsEditing(true);
setEditID(id);
setKegiatan(specificItem.title);
}
const completeItem = (id) => {
dispatch(completeItemList({id: id}));
}
return (
<section className="section-center">
<Navbar/>
<form className="kegiatan-form" onSubmit={handleSubmit}>
{alert.show && <Alert />}
<h3>Daftar Kegiatan</h3>
<div className="form-control">
<input
type="text"
className="kegiatan"
placeholder='contoh: beli beras'
value={kegiatan}
onChange={(e) => setKegiatan(e.target.value)}
/>
<button className="submit-btn" type="submit">
{isEditing ? 'edit' : 'submit'}
</button>
</div>
</form>
{list.length > 0 &&
<div className="kegiatan-container">
<List completeItem={completeItem} removeItem={removeItem} editItem={editItem}/>
<button className="clear-btn" onClick={clearList}>
hapus semua kegiatan
</button>
</div>
}
</section>
);
}
export default App
And this is my reducer code
import { createSlice } from '@reduxjs/toolkit'
const initialState = {
list: []
}
export const listSlice = createSlice({
name: 'list',
initialState,
reducers: {
addToList: (state, action) => {
console.log(action.payload.title);
return [...state.list, {id: new Date().getTime().toString(), title: action.payload.title, complete: false}];
},
editToList: (state, action) => {
return [...state.list, state.list.map((item) => {
if(item.id === action.payload['id']) {
return {...item, title: action.payload['kegiatan']};
}
return item;
})]
},
deleteListItem: (state, action) => {
return state.list.filter((item) => item.id !== action.payload.id);
},
clearAllList: () => {
return initialState;
},
completeItemList: (state, action) => {
return [...state.list, state['list'].map((item) => {
if(item.id === action.payload['id']) {
return {...item, complete: !state.list.complete};
}
return item;
})]
}
},
})
export const { completeItemList, editToList, addToList, deleteListItem, clearAllList} = listSlice.actions
export default listSlice.reducer
Upvotes: 0
Views: 997
Reputation: 29
try spreading the whole state before spreading just the list item within the state. Instead of :
return [...state.list, {id: new Date().getTime().toString(), title: action.payload.title, complete: false}];,
do :
return{...state, [...state.list, {id: new Date().getTime().toString(), title: action.payload.title, complete: false}];}
Upvotes: 1