Javascript 句柄函数上未定义的状态
我正在创建一个带有持续响应状态的简单测验,目前我一直在试图弄清楚为什么我的HandleanSwirclick函数中未定义responseState。如果每次单击都会触发此函数,则此函数将在很久以后触发。到那时,所有的州都应该设置好了Javascript 句柄函数上未定义的状态,javascript,reactjs,react-hooks,Javascript,Reactjs,React Hooks,我正在创建一个带有持续响应状态的简单测验,目前我一直在试图弄清楚为什么我的HandleanSwirclick函数中未定义responseState。如果每次单击都会触发此函数,则此函数将在很久以后触发。到那时,所有的州都应该设置好了 const Question: React.FC<IProps> = (props) => { const [responseState, setResponseState] = useState([]); const [question, 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>
)};
const问题:React.FC=(道具)=>{
const[responseState,setResponseState]=useState([]);
const[question,setQuestion]=useState(props.id);
const[answers,setAnswers]=useState([]);
const[choice,setChoice]=useState();
常量InitialResponseEstate=()=>{
常数数据={
持续时间:“00:01:00”,
范例进展:1,
问题:props.id,
答:"一",,
}
post(`${host}/api/responseState/`,数据)
.然后(()=>{
log(“创建了初始响应状态”);
})
.catch((错误)=>{
控制台日志(err);
})
}
const getData=async()=>{
等待axios([
get(`${host}/api/question/${question}`),
get(`${host}/api/responseState/examTakerProgress/1/question/${props.id}`)
])
.然后(axios.spread)((问题数据,回答数据)=>{
如果(!responseData.data.length>0){
initialResponseState();
}
SetResponseData(响应数据);
设置问题(questionData.data);
设置答案(问题数据、数据、答案);
setChoice(responseData.data.length>0?responseData.data[0]。答案:“”);
设置超时(()=>{
props.toggleLoading();
}, 50);
}))
.catch(err=>console.error(err));
};
useffect(()=>{
getData()
}, [])
const handleAnswerClick=async(编号:number)=>{
setChoice(数字);
常数数据={
持续时间:“00:01:00”,
范例进展:1,
问题:props.id,
答:号码,,
}
等待axios.put(`${host}/api/responseState/${responseState[0].id}/`,数据)
。然后((数据)=>{
控制台日志(数据);
console.log('选项更改为:'+编号);
})
.catch((错误)=>{
控制台日志(err);
})
}
如果(道具装载){
返回
}
返回(
{question.label}
{question.description}
{answers.map((答案,索引)=>{
if(answer.id==选项){
返回
}否则{
返回{
把手单击(应答器id)
}}>
}
}
)}
)};
有人能解释一下发生这种情况的原因吗?基于这句话
const[responseState,setResponseState]=useState({})代码>,
responseState
是一个对象
但是在handleAnswerClick
函数中,您将其用作数组${responseState[0].id}
请注意,如果对象具有0
键,这实际上是可行的,但由于您得到的是未定义键,因此情况并非如此 responseState
未定义的原因。
最明显的是将responseState
设置为未定义
调用setResponseState
的唯一位置是getData
中的setResponseState(responseData.data)
,因此请检查responseData.data
是否未定义
您永远无法调用setResponseState
,初始状态是一个对象,但您尝试获取responseState[0]。id
我不确定您正在处理的数据类型,但是如果您定义了const[responseState,setResponseState]=useState({})
使用默认值useState
作为{}
,然后尝试访问responseState[0].id
,出现两种情况
您有一个带有数字键的对象,或者有一个数组,但如果有数组,则应将初始值声明为数组
但这并不是问题所在,问题在于您可能永远无法访问调用setResponseState(responseData.data)的部分
然后您将拥有responseState
成为{}
,当尝试执行responseState[0]
时,它将是未定义的,当调用responseState[0]时,id
您将收到一个错误,说明您无法读取未定义的的id
解决这个问题的方法
调试代码,确保api调用返回您期望的内容,并setResponseState(responseData.data)代码>被调用
请检查responseState[0]
是否存在,然后再尝试访问responseState[0]。id
我可以提供更多帮助,但您没有添加更多信息,因此很难提供帮助,但我认为这就是问题所在基本上,当问题第一次加载时,我正在创建一个ResponseEstate,如果问题随后被重新加载,则状态已经存在,因为它已被持久化。这意味着我还必须确保在ResponseEstate仍然不存在的第一种情况下调用SetResponseEstate
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);
})}
啊,是的,我在测试一个理论,但忘了把它改回来,但问题是我的handleClick从来没有得到数据,这对我来说很奇怪,因为数据是在以前设置的。。错误:TypeError:无法读取Undelinedwell的属性“id”,这只是意味着未正确设置数据。我正在获取所需的数据。问题是由于某些原因,HandleanServlick未获取ResponseState,这很奇怪,因为此状态是在触发handleClick之前设置的。我不明白为什么在触发函数时它不存在错误:问题。tsx:101未捕获(承诺中)类型错误:无法读取pro