简体   繁体   中英

How to use spread operator for nested objects in react?

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)

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],
  };

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM