放大 dynamodb graphql fetch 函数在循环中无限运行

Posted

技术标签:

【中文标题】放大 dynamodb graphql fetch 函数在循环中无限运行【英文标题】:amplify dynamodb graphql fetch function is running infinite in loop 【发布时间】:2021-06-27 02:56:17 【问题描述】:

我正在尝试使用 graphql(AWS 放大 reacjs 设置)从 dynamodb 获取记录。我创建了一个组件 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.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>
    );

【问题讨论】:

请在此处找到完整的代码库github.com/smaranneducations/react-amplified/blob/test/src/… 【参考方案1】:

setTodos 正在重新安装组件,因此 useEffect 主体再次运行。

如果你注释掉setTodos它应该可以正常运行。

您可以使用React.memo 来比较道具而不是虚拟 dom,但它仍然会进行无用的获取。考虑重组您的应用程序,以便提取发生在上一层。

【讨论】:

【参考方案2】:

正如@arti91 所说,这是因为您正在更新状态,并且这样做会重新渲染组件并再次运行 useEffect 钩子。 如果您已经获取数据,一个可能的解决方案是检查钩子内部。

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

【讨论】:

如果我添加这个条件,那么 fetchTodos() 将不会被调用,因为 todos 在开始时是空的,因为 fetchTodos() 不会被调用状态不会改变,所以输出将为空白 我不确定我是否理解正确。您是说“if check”不正确并且“todos”为空时不调用 fetchTodos() 吗?在这种情况下尝试: if (todo.length === 0) fetchTodos() 【参考方案3】:

代替这段代码:

 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 
       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)
    

出现此问题是因为 Promise 仍处于预构建阶段,因此如果我们给它一些时间,它可以完成循环并获取值来存储它。

【讨论】:

await 等于 .then - 只是更新的语法 在 map 下添加了一个 return 并且它起作用了,我错过了 todo.map((todo, index) => return ( todo.name todo.description ) ) 但为什么我们需要返回for map 因为它等于循环 你可以使用=&gt; (语法代替=&gt; return (

以上是关于放大 dynamodb graphql fetch 函数在循环中无限运行的主要内容,如果未能解决你的问题,请参考以下文章

自动 DynamoDB 数据库检查 | ReactJS + AWS 放大

在 AWS Amplify GraphQL DynamoDB 中按另一个表的字段(也称为交叉表或嵌套过滤)过滤列表查询

调用graphql api时Flutter aws放大不返回数据

如何创建一个 lambda 函数来更新放大的新记录?

查询不会通过 GraphQL 从 DynamoDB 返回某些项目

Apollo GraphQL DataLoader DynamoDb