Я пытаюсь получить записи из Dynamodb с помощью graphql (AWS усиливает настройку reacjs). Я создал компонент CTCards и использую его в App.js
Проблема, с которой мы сталкиваемся, заключается в том, что функция fetchTodos работает в бесконечном цикле, хотя в базе данных есть только две записи, и я получаю ровно 2 записи, но эта функция работает в бесконечном цикле
Когда я комментирую код загрузки, программа работает, как ожидалось.
//== CTCards ( component which is giving issue) ===
function CTCards(props) {
const [todo, setTodos] = useState([]);
useEffect(() => {
fetchTodos();
}, []);
const fetchTodos = async () => {
try {
// == this-block ===
const todoData = await API.graphql(graphqlOperation(listTodos));
const todoList = todoData.data.listTodos.items;
console.info('To Do List', todoList);
setTodos(todoList);
// == /this-block ===
} catch (error) {
console.info('error on fetching to do list', error);
}
};
return (
<div style = {{color: "red"}}>
{todo.map((todo, index) => {
<div style = {{color: "red"}}>
<div>{todo.name}</div>
<div>{todo.description}</div>
</div>
})}
</div>
)
}
//== App.js code ===
function App() {
return (
<div>
<CTCards/>
</div>
);
}





setTodos повторно монтирует компонент, поэтому корпус useEffect снова работает.
Если вы закомментируете setTodos, он должен работать нормально.
Вы можете использовать React.memo для сравнения свойств, а не виртуального домена, но он все равно будет выполнять бесполезную выборку. Подумайте о реструктуризации вашего приложения, чтобы выборка происходила на один уровень выше.
Как сказал @ arti91, это вызвано тем, что вы обновляете состояние и делаете это, реагируя на повторный рендеринг компонента и снова запускает ловушку useEffect. Возможным решением этой проблемы может быть проверка внутри ловушки, если вы уже получили данные.
useEffect(() => {
if (!todos) {
fetchTodos();
}
}, []);
Если я добавлю это условие, то fetchTodos () не будет вызываться, так как todos пуст в начале, и поскольку fetchTodos () не будет вызываться, статус не изменится, поэтому вывод будет пустым.
Я не уверен, что правильно это понимаю. Вы говорите, что проверка «if» неверна и fetchTodos () не вызывается, когда «todos» пусто? в этом случае попробуйте: if (todo.length === 0) {fetchTodos ()}
Вместо этого кода:
try {
// == this-block ===
const todoData = await API.graphql(graphqlOperation(listTodos));
const todoList = todoData.data.listTodos.items;
console.info('To Do List', todoList);
setTodos(todoList);
// == /this-block ===
} catch (error) {
console.info('error on fetching to do list', error);
}
Попробуйте этот код:
try {
const todoData = API.graphql({ query: queries.listTodos }).then(response => {
setTodos(response.data.listTodos.items);
}).catch(err => {
console.info(err);
});
} catch (err) {
console.info('error facing Todos:', err)
}
Эта проблема возникает из-за того, что Promise все еще находится на этапе предварительной сборки, поэтому, если мы дадим ему некоторое время, он сможет завершить цикл и получить значение для его сохранения.
await равен .then - только новый синтаксис
Добавлен возврат под картой, и он сработал, чего мне не хватало {todo.map ((todo, index) => {return (<div key = {todo.id? Todo.id: index}> <div className = "lname" > {todo.name} </div> <div className = "ldesc"> {todo.description} </div> </div>)})} но зачем нам возврат для карты, поскольку он равен циклу
вы можете использовать синтаксис => ({ вместо => {return (
Полный код можно найти здесь github.com/smaranneducations/react-amplified/blob/test/src/…