skip to Main Content

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


  1. make sure that are using the useSelector hook in the component that need to access the note state

    you can add console.log to try find issue in redux actions

    Login or Signup to reply.
  2. Try importing all the notes from redux, and when you have them run your filter/find function.

    const notes = useSelector((state) => state.notes);
    const [note, setNote] = useState(null)
    
    useEffect(() => {
      const note = notes.filter((note) => note._id == id);
      setNote(note);
    }, [notes]);
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search