0

I am a newbie to React and stuck in structuring the object spread code in the reducer. The state is being stored as

{
  user: name,
  userAuth: null,
  errors: error,
  quizScores: [
    {
      quizId: 1,
      questionId: 12345,
      selectedOption: optionTwo,
      result: true,
    },
    {
      quizId: 2,
      questionId: 12345,
      selectedOption: optionTwo,
      result: true,
    }
  ]
}

Upon dispatch I want to update the State to append the object (below) to the other objects lying in 'quizScores'

{
  quizId: 2,
  questionId: 12345,
  selectedOption: optionTwo,
  result: true,
}

What I am trying is:

case ADD_SCORE:
    return {
      ...state,
      quizScores:{...state[quizScores],action.payload}
    };

Would be glad to get a little insight on how to use the spread operator to copy the previous objects and how to append the new one to it. If you think, I can use a better structure to store the data, I would be grateful to learn that as well. My goal is to simply continue to add all questionwise performance to be stored in the state. Thanks!!

I am using useState hook to create quizScores data in a functional component and triggering a function call (handleQuizScore) to below :

  const handleQuizScore = (questionData) => {
    dispatch({
      type: ADD_SCORE,
      payload: questionData,
    });
  };

Here is the entire reducer function that handles the state:

const authReducer = (state, action) => {
  switch (action.type) {
    case SUCCESS_REGISTER:
    case FAIL_REGISTER:
      return {
        ...state,
        userAuth: null,
        errors: action.payload,
      };
    case SUCCESS_LOGIN:
      localStorage.removeItem("token");
      localStorage.setItem("token", action.payload.token);
      console.log(action.payload.token);
      return {
        ...state,
        userAuth: true,
        errors: null,
      };
    case FAIL_LOGIN:
      return {
        ...state,
        userAuth: null,
        errors: action.payload,
      };
    case SET_ERROR:
      return {
        ...state,
        errors: action.payload,
      };
    case CLEAR_ERROR:
      return {
        ...state,
        errors: null,
      };
    case SET_USER:
      return {
        ...state,
        user: action.payload,
        userAuth: true,
        errors: null,
      };
    case AUTH_ERROR:
      return {
        ...state,
        errors: action.payload,
        userAuth: null,
      };
    case LOG_OUT:
      localStorage.removeItem("token");
      return {
        ...state,
        userAuth: null,
        errors: action.payload,
      };
    case ADD_SCORE:
      return {
        ...state,
        quizScores: [...state.quizScores, action.payload],
      };
    default:
      return state;
  }
};

The functional component in which useState is used:

const QuizQuestion = (props) => {
  const { clearError, userAuth, user, handleQuizScore } = useContext(
    AuthContext
  );
  let [questionData, handleQuizQuestion] = useState({
    selectedOption: "",
    result: "",
    quiz: "",
    questionId: "",
  });

  let { selectedOption, result, quiz, questionId } = questionData;
  const { question, toggleIsAnswered, quizId } = props;

  const handleOptionChange = (e) => {
    const { value } = e.target;
    console.log(question.answer);
    handleQuizQuestion({
      ...questionData,
      quiz: quizId,
      questionId: question._id,
      selectedOption: value,
    });
  };

  const resultCheck = (questionData) => {
    let flag = selectedOption === question.answer ? "true" : "false";
    handleQuizQuestion({
      ...questionData,
      result: flag,
    });
  };
  const handleVote = async (e) => {
    e.preventDefault();
    resultCheck(questionData);
    console.log("handleQuizQuestion", questionData);
    await handleQuizScore(questionData);
    toggleIsAnswered();
  };

return ( and so on)

5
  • Why is quizScores not an array, but an object? Commented Sep 29, 2020 at 21:27
  • 1
    Use dot notation { ...state.quizScores, action.payload }; Commented Sep 29, 2020 at 21:28
  • Agree with @Tobi, your state shape doesn't appear to be valid syntax. Commented Sep 29, 2020 at 21:30
  • @Tobi Thanks Tobi and kind user and Drew !! I have changed it to an array. Commented Sep 29, 2020 at 21:56
  • @Ravi Where did you use useState and useDispatch in the functional component? Commented Sep 30, 2020 at 3:21

1 Answer 1

3

state[quizScores] means to take the variable quizScores, evaluate it, and use that value as the key into object state. quizScores is likely undefined. Use the string literal for the key state["quizScores"] or more common and preferable, dot notation, state.quizScores to access and spread that array value in.

case ADD_SCORE: 
  return {
    ...state,
    quizScores: [...state.quizScores, action.payload],
  };
Sign up to request clarification or add additional context in comments.

6 Comments

Thanks for your answer and the explanation of variable. This is an awesome community that I just discovered today. While using the above structure I am getting an error "TypeError: state.quizScores is not iterable". From what I understand 'quizScores' is an array to store a series of objects like { quizId: 2, questionId: 12345, selectedOption: optionTwo, result: true, }
@Ravi Are you using react-redux, or a useReducer react hook? Do you mind updating your question to include your entire reducer function and initial state, and any action creators it handles? It seems that either (a) your initial state in the question is different, or (b) your state shape is mutated over time.
I just updated the question to include the reducer function as well. I am using useState hook in a functional component to create the data object that I am trying to append to the quizScores array in the reducer function to generate state.
@Ravi Thanks. Can you also copy/paste exactly what the initial state is that you pass to your reducer function.
Thanks so much for helping. I just pasted the functional component code as well where I am generating the state elements to be stored in quizScores.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.