Reputation: 1
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)
Upvotes: 0
Views: 3452
Reputation: 202836
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],
};
Upvotes: 3