#reactjs #google-cloud-firestore #react-hooks
# #reactjs #Google-облако-firestore #реагирующие перехваты
Вопрос:
Я пытаюсь получить набор вопросов из базы данных Firestore, а затем сохранить их в локальном массиве для последующего использования в викторине. Поскольку я работаю над извлечением данных, они выполняются асинхронно. Я уже сталкивался с этим раньше, и решением был useEffect()
компонент перехвата и условного рендеринга.
В настоящее время мой код выглядит следующим образом:
var questions = [];
var collection = useRef('Planning');
var [loading, setLoading] = useState(true);
useEffect(() => {
if (props.track === 'Testing amp; Deployment') {
collection.current = 'Test_Deploy';
} else {
collection.current = props.track;
}
if(questions.length !== 0){
setLoading(false)
} else {
var questionSet = db.collection('Quizzes').doc(collection.current).collection('Questions')
questionSet.withConverter(questionConverter).get().then(function(response) {
response.forEach(document => {
var question = document.data();
// running asynch - need to address
console.log('Question in')
questions.push(question)
})
})
setLoading(false)
}
}, [props.track, questions])}
В зависимости от того, где setLoading()
находится, компонент либо вообще не будет повторно отображаться, либо будет дважды извлекать данные из Firestore. Я useCallback()
пытался безрезультатно поиграть, а также увидел, что это может быть проблемой с React StrictMode
.
Любые советы о том, как исправить мой код, чтобы повторно отобразить страницу после получения всех вопросов, без их двойной выборки?
Комментарии:
1. К вашему сведению,
questions
каждый цикл рендеринга будет сбрасываться обратно в пустой массив[]
. Это должно быть частью состояния вашего компонента. Действительно ли ваш вопрос касается однократной выборки данных при монтировании компонента?2. Да, это, вероятно, лежит в основе проблемы. До этого я пытался использовать компонент класса, но обнаружил, что обновить массив состояний сложно.
Ответ №1:
Для однократной выборки данных при монтировании компонента вы можете указать пустой массив зависимостей. Я также предлагаю переместить questions
объект в состояние локального компонента. Поскольку состояние обновляется в цикле, вы должны использовать обновление функционального состояния для добавления каждого нового вопроса в массив.
const [questions, setQuestions] = useState([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
const questionSet = db
.collection("Quizzes")
.doc(collection.current)
.collection("Questions");
questionSet
.withConverter(questionConverter)
.get()
.then(function (response) {
response.forEach((document) => {
const question = document.data();
setQuestions(questions => [...questions, question]);
});
});
setLoading(false);
}, []);
Если компоновщик жалуется на отсутствие зависимостей, вам нужно либо добавить их и поместить соответствующую условную проверку в выборку данных, либо добавить комментарий для игнорирования / отключения компоновщика для строки с массивом зависимостей, // eslint-disable-next-line react-hooks/exhaustive-deps
.
Комментарии:
1. Именно то, что мне нужно было сделать. Спасибо, Дрю!
Ответ №2:
Он будет повторно отображаться при изменении или обновлении реквизита, включая props.track
и questions
каждый раз, когда вы вставляете в него элемент. Итак, если вы хотите избавиться от него повторно, просто удалите из useEffect
like
useEffect(() => {
.......
}, [loading])} // remove from here and add `loading` here just
Комментарии:
1. Помещение простой загрузки в скобки все равно приведет к появлению предупреждения о том, что зависимости отсутствуют. Боюсь, я неправильно понимаю ваше исправление.