Состояние хуков реакции undefined для функции дескриптора - PullRequest
1 голос
/ 08 мая 2020
• 1000 К тому времени все состояния должны быть установлены.
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>
)};

Может ли кто-нибудь объяснить мне причину, по которой это происходит?

Ответы [ 3 ]

1 голос
/ 08 мая 2020

Причины, по которым responseState равно undefined.

  1. Наиболее очевидным является то, что вы устанавливаете responseState как undefined

Единственное место, куда вы звоните 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] это будет undefined, а при вызове responseState[0].id вы получите сообщение об ошибке, что вы не можете прочитать id из undefined .

Способы исправить это

  1. Отладьте свой код, убедитесь, что вызов api возвращает то, что вы ожидаете, и вызывается setResponseState(responseData.data);.

  2. Перед попыткой доступа проверьте, существует ли responseState[0]. responseState[0].id

Я буду Я мог бы помочь больше, но вы не добавили дополнительной информации, поэтому помочь трудно, но выше я думаю, что это проблема

1 голос
/ 08 мая 2020

На основе этой строки

const [responseState, setResponseState] = useState({});,

, responseState является объектом.

но в функции handleAnswerClick вы используете его как array ${responseState[0].id}.

Обратите внимание, что это действительно работает, если у объекта есть ключ 0, но поскольку вы получаете undefined, это не так.

0 голосов
/ 08 мая 2020

В основном я создаю responseState, когда вопрос загружается в первый раз, если вопрос впоследствии перезагружается, состояние уже существует, поскольку оно сохраняется. Это означает, что я также должен вызвать setResponseState для первого случая, когда ResponseState все еще не существует.

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);
    })}
...