Flashcards Project React/Redux - Cannot read properties of undefined (reading 'name')

I can currently create new topics, create new quizzes and I see that they are being added to state with the redux inspector tools but when I click on a newly created quiz I get this error: Cannot read properties of undefined (reading ‘name’).

Here is my quiz slice:

import { createSlice } from "@reduxjs/toolkit";
import { addQuizToTopic } from "../topics/topicsSlice";

const quizzesSlice = createSlice({
    name: 'quizzes',
    initialState: {
        quizzes: {}
    },
    reducers: {
        addQuiz: (state, action) => {
            const { quizId, name, topicId, cardIds } = action.payload;
            state.quizzes[quizId] = {
                quizId: quizId,
                name: name,
                topicId: topicId,
                cardIds: cardIds
            }
        }
    }
})

export const addQuizAddQuizId = quiz => {
    const { quizId, name, topicId, cardIds } = quiz;
    return (dispatch) => {
        dispatch(quizzesSlice.actions.addQuiz(quiz));
        dispatch(addQuizToTopic( { quizId: quizId, topicId: topicId } ));
    }
};

export const selectQuizzes = (state) => state.quizzes.quizzes;
export const { addQuiz } = quizzesSlice.actions;
export default quizzesSlice.reducer;

And here is my NewQuizForm.js :

import React, { useState } from "react";
import { useHistory } from "react-router-dom";
import { v4 as uuidv4 } from "uuid";
import ROUTES from "../app/routes";
import { useSelector, useDispatch } from "react-redux";
import { selectTopics } from "../features/topics/topicsSlice";
import { addQuizAddQuizId } from "../features/quizzes/quizzesSlice";
import { addCard } from "../features/cards/cardsSlice";

export default function NewQuizForm() {
  const dispatch = useDispatch();
  const [name, setName] = useState("");
  const [cards, setCards] = useState([]);
  const [topicId, setTopicId] = useState("");
  const history = useHistory();
  const topics = useSelector(selectTopics);

  const handleSubmit = (e) => {
    e.preventDefault();
    if (name.length === 0) {
      return;
    }
    const cardIds = [];

    cards.forEach(card => {
      let newCard = {
        front: card.front,
        back: card.back,
        id: uuidv4()
      };
      cardIds.push(newCard.id)
      dispatch(addCard(newCard))
    })
    
    let newQuiz = {
      name: name,
      topicId: topicId,
      cardIds: cardIds,
      quizId: uuidv4()
    }

    dispatch(addQuizAddQuizId(newQuiz))

    history.push(ROUTES.quizzesRoute());
  };

  const addCardInputs = (e) => {
    e.preventDefault();
    setCards(cards.concat({ front: "", back: "" }));
  };

  const removeCard = (e, index) => {
    e.preventDefault();
    setCards(cards.filter((card, i) => index !== i));
  };

  const updateCardState = (index, side, value) => {
    const newCards = cards.slice();
    newCards[index][side] = value;
    setCards(newCards);
  };

  return (
    <section>
      <h1>Create a new quiz</h1>
      <form onSubmit={handleSubmit}>
        <input
          id="quiz-name"
          value={name}
          onChange={(e) => setName(e.currentTarget.value)}
          placeholder="Quiz Title"
        />
        <select
          id="quiz-topic"
          onChange={(e) => setTopicId(e.currentTarget.value)}
          placeholder="Topic"
        >
          <option value="">Topic</option>
          {Object.values(topics).map((topic) => (
            <option key={topic.id} value={topic.id}>
              {topic.name}
            </option>
          ))}
        </select>
        {cards.map((card, index) => (
          <div key={index} className="card-front-back">
            <input
              id={`card-front-${index}`}
              value={cards[index].front}
              onChange={(e) =>
                updateCardState(index, "front", e.currentTarget.value)
              }
              placeholder="Front"
            />

            <input
              id={`card-back-${index}`}
              value={cards[index].back}
              onChange={(e) =>
                updateCardState(index, "back", e.currentTarget.value)
              }
              placeholder="Back"
            />

            <button
              onClick={(e) => removeCard(e, index)}
              className="remove-card-button"
            >
              Remove Card
            </button>
          </div>
        ))}
        <div className="actions-container">
          <button onClick={addCardInputs}>Add a Card</button>
          <button>Create Quiz</button>
        </div>
      </form>
    </section>
  );
}

Any help would be greatly appreciated,
Thanks,
Mick

Hey not sure if you solved your problem yet, but I did observe some differences in our code. For your dispatch(addQuizAddQuizId( ))

I subbed in the following.

// create the new quiz here
    dispatch(createNewQuiz({
      id: uuidv4(),
      name: name,
      topicId: topicId,
      cardIds: cardIds,
    }))

I also subbed in id instead of quizId in my quizzesSlice. Maybe it makes a difference. Worth a try.

import { createSlice } from '@reduxjs/toolkit'
import { addQuizId } from '../topics/topicsSlice';

export const quizzesSlice = createSlice({
    name: 'quizzes',
    initialState: {
        quizzes: {}
    },
    reducers: {
        addQuiz: (state, action) => {
            const { id, name, topicId, cardIds } = action.payload;
            state.quizzes[id] = {
                id: id,
                name: name,
                topicId: topicId,
                cardIds: cardIds
            };
        }
    }
})

export const createNewQuiz = (quiz) => {
    const { id, topicId } = quiz;
    return (dispatch) => {
        dispatch(quizzesSlice.actions.addQuiz(quiz));
        dispatch(addQuizId({ quizId: id, topicId: topicId }));
    }
}


export default quizzesSlice.reducer;
export const { addQuiz } = quizzesSlice.actions;
export const selectQuizzes = state => state.quizzes.quizzes;

Let me know if that helped any

Cecil

Thanks for the reply unfortunately that didn’t work.