Усилить Dynamodb функция выборки graphql работает бесконечно в цикле

Я пытаюсь получить записи из 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>
    );
}

Полный код можно найти здесь github.com/smaranneducations/react-amplified/blob/test/src/…

Smarann Educations 31.03.2021 08:19
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
1
1
51
3

Ответы 3

setTodos повторно монтирует компонент, поэтому корпус useEffect снова работает.

Если вы закомментируете setTodos, он должен работать нормально.

Вы можете использовать React.memo для сравнения свойств, а не виртуального домена, но он все равно будет выполнять бесполезную выборку. Подумайте о реструктуризации вашего приложения, чтобы выборка происходила на один уровень выше.

Как сказал @ arti91, это вызвано тем, что вы обновляете состояние и делаете это, реагируя на повторный рендеринг компонента и снова запускает ловушку useEffect. Возможным решением этой проблемы может быть проверка внутри ловушки, если вы уже получили данные.

useEffect(() => {
   if (!todos) {
       fetchTodos();
   }
}, []);

Если я добавлю это условие, то fetchTodos () не будет вызываться, так как todos пуст в начале, и поскольку fetchTodos () не будет вызываться, статус не изменится, поэтому вывод будет пустым.

Smarann Educations 31.03.2021 14:31

Я не уверен, что правильно это понимаю. Вы говорите, что проверка «if» неверна и fetchTodos () не вызывается, когда «todos» пусто? в этом случае попробуйте: if (todo.length === 0) {fetchTodos ()}

Sjnao 31.03.2021 15:29

Вместо этого кода:

 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 - только новый синтаксис
xadm 31.03.2021 12:33

Добавлен возврат под картой, и он сработал, чего мне не хватало {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>)})} но зачем нам возврат для карты, поскольку он равен циклу

Smarann Educations 01.04.2021 16:45

вы можете использовать синтаксис => ({ вместо => {return (

xadm 01.04.2021 17:06

Другие вопросы по теме