Yustina Yasin
Yustina Yasin

Reputation: 319

Component update but state does not update redux toolkit

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

enter image description here

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

Answers (1)

Eme.eth
Eme.eth

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

Related Questions