Реагирует на тот факт, что все динамические данные c должны быть в своем состоянии. Это включает даже данные DOM, такие как входные значения формы. То, что вы здесь делаете, совершенно неверно.
Слишком много ошибок вы делаете здесь
Ошибка 1:
Не используется React State. Не могу выделить это достаточно. Все ваши динамические данные c должны go перейти в состояние реакции - year
, totalTests
- все должно быть объявлено как состояние реакции. Таким образом React может отслеживать изменения данных и оптимизировать производительность.
Ошибка 2:
Не использовать useEffect()
для выполнения побочных эффектов. Побочный эффект не должен выполняться при root функции. Тебе не следует. Реакт никогда не узнает, что, черт возьми, происходит внутри вашей функции. Используйте правильный useEffect()
с соответствующим массивом зависимостей
Ошибка 3:
Это ошибка JavaScript. Не используйте var
для объявления переменных. Имеет проблемы с областями видимости. Используйте let
для переменных и const
для констант.
Ошибка 4:
Не используйте эффективные и встроенные JavaScript методы вместо написания собственной сортировки и других алгоритмов.
Консольный журнал в этом компоненте вызывает инфинитив. Почему?
Поскольку console.log находится в root функции. Каждый раз, когда происходит обновление, и когда React необходимо повторно выполнить рендеринг компонента, функция будет вызываться снова с новыми значениями состояния. Так как ваш код заставил функцию работать бесконечно l oop, запись в консоль осуществлялась бесконечно. Вот почему гораздо важнее использовать useState
и useEffects
, чтобы React знал, что выполнять и что обновлять и не допускать бесконечного l oop.
Надеюсь, что он ответит ваши вопросы, следующий переход к решению
Решение
Я должен дать понять, что не могу и не буду переписывать весь ваш код, и убедиться, что все работает, это ваша работа, но я, однако, я Я более чем рад помочь вам и объяснить их.
Прежде чем перейти к React, позвольте мне прояснить ситуацию в JavaScript space
Избегать использования var
var
неправильно определены в JavaScript, что приводит к большим путаницам и головным болям при отладке. Поэтому используйте новые ключевые слова для объявления переменных
let
для переменных const
для константы
Они ограничены и ведут себя так же, как вы ожидайте, что они будут вести себя.
Если что-то существует, не переписывайте это - используйте встроенные методы
Вместо написания собственного алгоритма сортировки, используйте JavaScript встроенный sort
метод. Объятие веселье национальное программирование
Ваш алгоритм сортировки можно заменить на
const sortedPrograms = [ ...programs ].sort((a, b) =>
a.tests[0].date > b].tests[0].date ? -1 : 1
)
Причина, по которой я использовал [ ...programs ].sort
вместо programs.sort
, заключается в том, что sort
метод изменяет исходный массив, что нежелательно в React, поэтому я мелко клонировал массив.
Для следующих двух циклов for, я полагаю, вы пытаетесь сгруппировать программы по годам. (Поправьте меня, если я ошибаюсь).
Эти десятки строк кода можно легко заменить моим любимым JavaScript reduce
методом.
Ваш алгоритм группировки можно заменить на
const programsGroupedByYear = programs.reduce(
// acc - Accumulated, cur - current item
(acc, cur) => {
const year = moment(cur.tests[0].date, 'YYYY/MM/DD').format('YYYY');
return {
...acc,
// Check if the year index exist in the accumulated object
// if yes, append it to the array
// if no, create a new array
// and store in the year index
[year]: acc[year] ? [ ...acc[year], cur ] : [cur]
}
}
, {})
Вот и все, ваши 20+ строк из двух для циклов могут быть заменены на 6+ строк Array.reduce
метода.
Сохраните все данные в состоянии реакции
Аполлон useQuery
представляет собой пользовательский хук, что означает, что вывод data
является состоянием реакции. Поэтому необходимо объявить любое новое состояние здесь, кроме переменной для хранения отсортированных и сгруппированных данных.
Переместить все побочные эффекты внутрь useEffects
Не должно быть никаких побочных эффектов на root функции. Все они должны go внутри useEffects
useEffect(() => {
// All your side effects goes in here
}, [deps])
// React will track the items in dep array,
// if there's any change in them, React will call this useEffect
Если побочные эффекты не разрешены в root функции, что тогда должно быть разрешено в root? Это приводит нас к
Всегда используйте хуки в root вашей функции
Не вызывайте хуки внутри циклов, условий или вложенных функций.
Заключительный совет
Используйте JavaScript как способ функционального программирования, особенно если вы используете React вместо того, чтобы думать о циклах и мутации данных
Я очень предлагаю вам использовать Rule of Hooks плагин для линтера.
Итак, завершение,
GIST вашего кода
const StatusBar = () => {
const { data: curProgram_data } = useQuery(GET_CUR_PROGRAM);
const { data: programs_data, loading: programs_loading } =
useQuery(GET_PROGRAMS);
const { data: tests_data, loading: tests_loading } = useQuery(GET_TESTS);
const { data: articles_data, loading: articles_loading } =
useQuery(GET_ARTICLES);
const [sortedProgram, setSortedProgram] = useState([]);
const [programsGroupedByYear, setProgramsGroupByYear] =
useState([]);
useEffect(() => {
if (!programs_loading) {
const _sortedPrograms = [ ...programs_data.programs ].sort((a, b) =>
a.tests[0].date > b].tests[0].date ? -1 : 1
)
setSortedProgram(_sortedPrograms)
const _programsGroupedByYear = programs.reduce(
(acc, cur) => {
const year = moment(cur.tests[0].date, 'YYYY/MM/DD').format('YYYY');
return {
...acc,
[year]: acc[year] ? [ ...acc[year], cur ] : [cur]
}
}
, {})
}
setProgramsGroupedByYear(__programsGroupedByYear)
}, [programs_data, programs_loading])
// Then place your if condition
if (programs_loading || tests_loading || articles_loading)
return <p>Loading ... </p>;
return (
<YourJSXCode />
)
}