1

I am trying to fetch records from dynamodb using graphql (AWS amplify reacjs setup). I have created a component CTCards and using this in App.js

The problem that we are facing is function fetchTodos is running in infinite loop though in Database there is only two records and I am getting exactly 2 records but this function is running in infinite loop

When I comment the fetching code then the program runs as expected

//== 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.log('To Do List', todoList);
            setTodos(todoList);
// == /this-block ===
        } catch (error) {
            console.log('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>
    );
}
1

3 Answers 3

1

The setTodos is remounting the component so the useEffect body runs again.

If you comment out the setTodos it should run normally.

You can use React.memo to compare props and not the virtual dom but it will still do a useless fetch. Consider restructuring your application so the fetch happens one layer above.

Sign up to request clarification or add additional context in comments.

Comments

1

As @arti91 said it s cause you are updating the state and doing so react rerenders the component and runs the useEffect hook again. A possible solution to this could be to check inside the hook if you already fetched the data.

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

2 Comments

If I add this condition then fetchTodos() will not be called as todos is empty in beginning and as fetchTodos() will not be called status will not change so output will be blank
I m not sure I understand that correctly. Are you saying that the "if check" is not correct and fetchTodos() is not called when "todos" is empty? in that case try with: if (todo.length === 0) { fetchTodos() }
0

Instead of this code:

 try {
       // == this-block ===
        const todoData = await API.graphql(graphqlOperation(listTodos));
        const todoList = todoData.data.listTodos.items;
        console.log('To Do List', todoList);
        setTodos(todoList);
       // == /this-block ===
    } catch (error) {
        console.log('error on fetching to do list', error);
    }

Try this code:

try {
       const todoData = API.graphql({ query: queries.listTodos }).then(response => {
        setTodos(response.data.listTodos.items);
      }).catch(err => {
        console.log(err);
      });
    } catch (err) {
        console.log('error facing Todos:', err)
    }

This issue occurs because the of the Promise that is still is prebuild phase so if we give it some time that it could complete the cycle and get the value to store it.

3 Comments

await equals to .then - just newer syntax
Added a return under map and it worked which I was missing {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> ) })} but why do we need a return for map as it is equal to loop
you can use => ({ syntax instead of => {return (

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.