I am creating a react app and for state management. When dispatch is called, it works fine and updating the value in the component. But the value is an empty array (may be initial state) in other components, when I tried to use it. It seems like the store value is updated but it is only available in only one component (from which use dispatch is called)
this is where it works,
import React from 'react'; import { useEffect } from 'react'; import { useDispatch } from 'react-redux'; import { setNote, deleteNote } from './action'; import { useSelector } from 'react-redux'; export default function Account() { const dispatch = useDispatch(); const notes = useSelector((state) => state.notes); console.log(notes); useEffect(() => { const token = localStorage.getItem('token'); if (token) { fetch('http://localhost:3000/notes', { method: 'GET', headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${token}`, }, }) .then((response) => response.json()) .then((data) => { dispatch(setNote(data)); }) .catch((error) => console.error(error)); } }, []); function redirect() { window.location.href = '/new'; } function handleEditButton(id) { window.location.href = `/edit/${id}`; } function handleDelete(id) { const token = localStorage.getItem('token'); fetch(`http://localhost:3000/notes/${id}`, { method: 'DELETE', headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${token}`, }, }) .then((response) => response.text()) .then((data) => { console.log(data); dispatch(deleteNote(id)); }) .catch((error) => console.error(error)); } return ( <div> <h1>Your Notes</h1> <button className="green" onClick={redirect}> Add New Note </button> {notes && notes.map((note) => ( <div className="note" key={note._id}> <h2>{note.title}</h2> <p>{note.content}</p> <p>Created: {note.dateCreated}</p> <p>Last Modified: {note.lastModified}</p> <button className="edit" onClick={() => handleEditButton(note._id)}> Edit Note </button> <button className="delete" onClick={() => handleDelete(note._id)}> Delete Note </button> </div> ))} </div> ); }
My action and reducer
export function addNote(notes) { return { type: 'ADD_NOTE', payload: notes } } export function updateNote(notes) { return { type: 'UPDATE_NOTE', payload: notes } } export function deleteNote(noteId) { return { type: 'DELETE_NOTE', payload: noteId } } export function setNote(notes) { return { type: 'SET_NOTE', payload: notes } }
const initialState = { notes: [] } export default function notesReducer(state = initialState, action) { switch (action.type) { case 'ADD_NOTE': return { ...state, notes: [...state.notes, action.payload] }; case 'UPDATE_NOTE': return { ...state, notes: state.notes.map(note => note.id === action.payload.id ? action.payload : note) }; case 'DELETE_NOTE': return { ...state, notes: state.notes.filter(note => note._id !== action.payload) }; case 'SET_NOTE': return { ...state, notes: action.payload }; default: return state } }
My app component.
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom'; import { Provider } from 'react-redux'; import { createStore } from 'redux'; import notesReducer from './reducer.js' import Account from './Account'; import Login from './Login'; import SignUp from './SignUp'; import Note from './Note'; import New from './New'; import Edit from './Edit'; const store = createStore(notesReducer); function App() { return ( <Provider store={store}> <Router> <Routes> <Route path="/login" element={<Login />} /> <Route path="/" element={<SignUp />} /> <Route path="/account" element={<Account />} /> <Route path="/display" element={<Note />} /> <Route path="/new" element={<New />} /> <Route path="/edit/:id" element={<Edit/>} /> </Routes> </Router> </Provider> ) } export default App;
here’s my edit component, one of component in which it is not working.
import React, { useState } from "react"; import { useSelector } from "react-redux"; import { useParams } from "react-router-dom"; export default function Edit() { const { id } = useParams(); const note = useSelector(state => state.notes.find(note => note._id === id)); const [title, setTitle] = useState(note.title); const [content, setContent] = useState(note.content); function handleEditNote() { const updatedNote = { id, title, content }; // dispatch an action to update the note in the store and send a request to update the note on the server } return ( <div> <div className="new"> <h1>Edit Note</h1> <label> Title: <br /> <input type="text" value={title} onChange={(e) => setTitle(e.target.value)} /> </label> <br /> <label> Content: <br /> <textarea value={content} onChange={(e) => setContent(e.target.value)} /> </label> <br /> <button onClick={handleEditNote}>Save Changes</button> </div> </div> ); }
even if I console log note in edit component, without mapping it. it logs empty array. Also, The account component (where it works), logs it as empty array at first, it is populated after the fetch and use dispatch.
I’m new to redux, please help.
2
Answers
make sure that are using the
useSelector
hook in the component that need to access thenote
stateyou can add console.log to try find issue in redux actions
Try importing all the notes from redux, and when you have them run your filter/find function.