Reputation: 394
I am creating a simple quiz with persisting response state and i am currently stuck trying to figure out why responseState is undefined in my handleAnswerClick function, this function is triggered much later if at all per click. By then the States should all be set.
const Question: React.FC<IProps> = (props) => {
const [responseState, setResponseState] = useState([]);
const [question, setQuestion] = useState<IStateProps>(props.id);
const [answers, setAnswers] = useState([]);
const [choice, setChoice] = useState();
const initialResponseState = () => {
const data = {
duration: '00:01:00',
examTakerProgress: 1,
question: props.id,
answer: '1',
}
axios.post(`${host}/api/responseState/`, data)
.then(() => {
console.log('Created the initial Response State');
})
.catch((err) => {
console.log(err);
})
}
const getData = async () => {
await axios.all([
axios.get(`${host}/api/question/${question}`),
axios.get(`${host}/api/responseState/examTakerProgress/1/question/${props.id}`)
])
.then(axios.spread((questionData, responseData) => {
if (!responseData.data.length > 0) {
initialResponseState();
}
setResponseState(responseData.data);
setQuestion(questionData.data);
setAnswers(questionData.data.answers);
setChoice(responseData.data.length > 0 ? responseData.data[0].answer : '');
setTimeout(() => {
props.toggleLoading();
}, 50);
}))
.catch(err => console.error(err));
};
useEffect(() => {
getData()
}, [])
const handleAnswerClick = async (number: number) => {
setChoice(number);
const data = {
duration: '00:01:00',
examTakerProgress: 1,
question: props.id,
answer: number,
}
await axios.put(`${host}/api/responseState/${responseState[0].id}/`, data)
.then((data) => {
console.log(data);
console.log('choice changed to :' + number);
})
.catch((err) => {
console.log(err);
})
}
if (props.loading) {
return <Loader/>
}
return (
<React.Fragment>
<h3>{question.label}</h3>
<p className='mb-3'>{question.description}</p>
<ListGroup as="ul">
{answers.map((answer, index) => {
if (answer.id === choice) {
return <ListGroup.Item key={answer.id} action active> <Answer key={index}
answer={answer}/></ListGroup.Item>
} else {
return <ListGroup.Item key={answer.id} action onClick={() => {
handleAnswerClick(answer.id)
}}><Answer key={index}
answer={answer}/></ListGroup.Item>
}
}
)}
</ListGroup>
</React.Fragment>
)};
Can someone explain me the reason why this is happening?
Upvotes: 2
Views: 3286
Reputation: 394
Basically i am creating a responseState when a question loads for the first time, if a question is afterwards reloaded the State is already there since it is persisted. This means i also have to make sure to call setResponseState for the first case where the ResponseState still does not exist.
const initialResponseState = () => {
const data = {
duration: '00:01:00',
examTakerProgress: 1,
question: props.id,
answer: '1',
}
axios.post(`${host}/api/responseState/`, data)
.then(() => {
setResponseState(res.data)
console.log('Created the initial Response State');
})
.catch((err) => {
console.log(err);
})}
Upvotes: 0
Reputation: 31565
responseState
is undefined
.responseState
to undefinedThe only place you call setResponseState
is in getData
where you have setResponseState(responseData.data);
, so please check if responseData.data
isn't undefined.
setResponseState
and the initial state is an object but you try to get responseState[0].id
I'm not sure what data type you are handling, but if you defined const [responseState, setResponseState] = useState({});
with the default value of useState
as {}
and then try to access responseState[0].id
, there is two things happening.
Either you have an object with number keys or you have an array, but if you have an array, you should declare the initial value as an array.
But this isn't the problem, the problem is that you might never get to the part where you call setResponseState(responseData.data);
and then you will have responseState
to be {}
and when trying to do responseState[0]
it will be undefined
, and when calling responseState[0].id
you will get an error saying that you cannot read id
of undefined
.
Debug your code, make sure that the api call returns what you are expecting and setResponseState(responseData.data);
is called.
Check if responseState[0]
exists before try to access responseState[0].id
I would be able to help more, but you didn't add more information, so it's hard to help, but above is what I think it's the problem
Upvotes: 1
Reputation: 10652
Based on this line
const [responseState, setResponseState] = useState({});
,
the responseState
is an object.
but in the handleAnswerClick
function you are using it as an array ${responseState[0].id}
.
Note that this actually works if the object has a 0
key but since you're getting undefined that is not the case.
Upvotes: 1