#javascript #reactjs #react-native
Вопрос:
Это мой код. Я хочу добавить новую статью расходов в начало списка. Я надеялся получить некоторую помощь в том, как я могу создать новые расходы в верхней части списка. Я продолжаю получать одну и ту же ошибку: слишком много перерисовок. React ограничивает количество рендеров, чтобы предотвратить бесконечный цикл. Как я могу это исправить?
import React, { useState } from "react";
import { Text, View, ScrollView } from "react-native";
import NewExpense from "../NewExpense";
import {
selectTitle,
selectPrice,
selectCategory,
} from "../../slices/dataSlice";
import { useSelector } from "react-redux";
const RenderedExpense = () => {
const title = useSelector(selectTitle);
const price = useSelector(selectPrice);
const category = useSelector(selectCategory);
const enteredData = {
id: Math.random().toString(),
title: title.disTitle,
price: price.disPrice,
category: category.disCategory,
};
const expense = enteredData;
const [expenseItems, setExpenseItems] = useState([]);
setExpenseItems([expense, ...expenseItems]);
return (
<View>
{
(title.disTitle,
price.disPrice,
category.disCategory ? <NewExpense /> : null)
}
{
expenseItems.map(() => {
<NewExpense key={enteredData.id} /> })
}
</View>
);
};
Комментарии:
1. Я думаю, что ваш бесконечный цикл начинается отсюда: const [expenseItems, setExpenseItems] = useState([]); setExpenseItems([расходы, …расходы]);
Ответ №1:
Вы вызываете свой setExpenseItems
внутри вашего непосредственно внутри вашего компонента, это приведет к бесконечному повторному отображению вашего компонента, потому что всякий раз, когда задано состояние, компонент повторно отображается. Таким образом, он будет просто продолжать устанавливать состояние и изменять его.
Если вы хотите установить состояние, как только компонент загрузится, вам следует использовать useEffect
крючок.
Подобный этому:
import React, { useState, useEffect } from "react";
...
const title = useSelector(selectTitle);
const price = useSelector(selectPrice);
const category = useSelector(selectCategory);
const enteredData = {
id: Math.random().toString(),
title: title.disTitle,
price: price.disPrice,
category: category.disCategory,
};
const expense = enteredData;
const [expenseItems, setExpenseItems] = useState([]);
useEffect(()=>{
setExpenseItems([expense, ...expenseItems]);
},[])
...
Обратите внимание, как я позвонил setExpenseItems
внутрь useEffect
. Он будет вызываться setExpenseItems
только при первом отображении компонента. useEffect также принимает список зависимостей, который определит, будет ли выполняться то, что когда-либо указано в функции. Но я передал пустой массив в качестве своей зависимости.
Смотрите здесь для получения дополнительной информации.
Ответ №2:
Выполнение a setState
запускает повторную визуализацию, поэтому у нас никогда не должно быть setState
внутри метода визуализации, иначе произойдет цикл infitine.
Поскольку у вас есть setExpenseItems([expense, ...expenseItems]);
внутренний метод визуализации, вы всегда будете получать это исключение.
Вы можете поместить эту деталь в эффект использования, который выполняется только при изменении значений в скобках, а не при каждом отображении компонента:
useEffect(() => {
const enteredData = {
id: Math.random().toString(),
title: title.disTitle,
price: price.disPrice,
category: category.disCategory,
};
const expense = enteredData;
setExpenseItems([expense, ...expenseItems]);
}, [title, price, category]);
Ответ №3:
Вы используете setExpenseItems([expense, ...expenseItems]);
без каких-либо условий. При обновлении состояния компонент будет повторно отправлен, состояние будет обновлено снова, компонент повторно отправлен и так далее… бесконечная рекурсия. Вам нужно поведение, аналогичное componentDidMount() в дизайне класса React. Обычно для этого вы используете крючок эффекта: https://reactjs.org/docs/hooks-effect.html
В вашем Примере:
useEffect(() => {
setExpenseItems([expense, ...expenseItems]);
})