【问题标题】:amplify dynamodb graphql fetch function is running infinite in loop放大 dynamodb graphql fetch 函数在循环中无限运行
【发布时间】: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>
    );
}

【问题讨论】:

标签: reactjs amazon-web-services graphql amazon-dynamodb amplify


【解决方案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 (
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-11-24
    • 2021-08-28
    • 1970-01-01
    • 1970-01-01
    • 2020-05-19
    • 1970-01-01
    • 2019-04-07
    相关资源
    最近更新 更多