简体   繁体   English

如何使用来自异步函数返回的 React 挂钩设置 state

[英]How to set state with React hooks from async fucntion return

I have a React module that makes a call to a function from an API in another JS module it imports.我有一个 React 模块,它从它导入的另一个 JS 模块中的 API 调用 function。 This function makes an async call to a flask route in my backend which returns a JSON object.这个 function 在我的后端对 flask 路由进行异步调用,该路由返回 JSON2668CFDE63131B459

setSearchData is a useState. setSearchData 是一个使用状态。

In my React app, I setSearchData(getData(searchTerm)) with the expectation that the getData(searchTerm) function will asynchronously return something.在我的 React 应用程序中,我 setSearchData(getData(searchTerm)) 期望 getData(searchTerm) function 将异步返回一些东西。 When my promsie is resolved it should pipe jason data as such:当我的承诺得到解决时,它应该 pipe jason 数据如下:

flask route -> searchAPI async func -> exported API func -> setState via hook flask 路由 -> searchAPI 异步函数 -> 导出 API 函数 -> 通过钩子设置状态

getsearch(search_term) -> flaskRoute(route, searchTerm) -> getSearchData(searchTerm) -> setSearchData( getSearchData(searchTerm) ) getsearch(search_term) -> flaskRoute(route, searchTerm) -> getSearchData(searchTerm) -> setSearchData(getSearchData(searchTerm))

This doesn't work of course.这当然行不通。 The JSON data does get returned but it never updates the state. JSON 数据确实会返回,但它永远不会更新 state。 It seems as if the state gets updated with null and doesn't wait for the promise to get resolved.似乎 state 已更新为null并且不等待 promise 得到解决。

How can I get an async function to play nice with React state which is itself async?如何让异步 function 与本身是异步的 React state 配合使用?

api_flask_routes.py api_flask_routes.py

from flask import jsonify, request

@bp.route('/search/<search_term>', methods=['GET'])
def getsearch(search_term):
    search_data = [
        ['stuff'],
        ['stuff'],
        ['stuff'],
        ...
    ]
    return jsonify(search_data)

SearchDataAPI.js SearchDataAPI.js

async function regularRoute({ route, searchTerm = '', method = 'GET' }) {
    const routeWithSearchTerm = `${route}/${searchTerm}`;
    const endpoint = `${HOST_IP_ADDRESS}${searchTerm ? routeWithSearchTerm : route}`;
    const configs = {
        method,
        mode: 'cors',
        headers: { 'Content-Type': 'application/json' },
    };

    return fetch(endpoint, configs)
        .then(res => res.json())
        .then(data => data)
        .catch((err) =>  console.error(err));
}

function getSearchData(searchTerm) {
   return flaskRoute("/api/search/", searchTerm); // returns json to importing module
}

MySearch.js this is a React component MySearch.js 这是一个 React 组件

import searchDataAPI from '../searchAPI/SearchDataAPI';

//// DATA RETRIEVAL FROM BACKEND ////
const [searchData, setSearchData] = useState(null);
const getSearchData = searchDataAPI.searchFunctions.getSearchData;

function handleSubmitSearch(e) {
  e.preventDefault();
  if (searchTerm.trim().length > 0) {
      setSearchData(null); // clears out previous search data
      setSearchData(getSearchData(searchTerm)); // this doesn't work!
      // more stuff...
    }
}

you have to wait for your function resolve by using.then() like the following:您必须等待您的 function 通过 using.then() 解决,如下所示:

 getSearchData(searchTerm).then(result => {
    setSearchData(result)
});

if it still return null, then you have to change your getSearchData() to async, so it can also return the resolve result like:如果它仍然返回 null,那么你必须将你的 getSearchData() 更改为异步,这样它也可以返回解析结果,如:

async function getSearchData(searchTerm) {
   return await flaskRoute("/api/search/", searchTerm).then(res => {
    return res;
  });
}

if that also doesn't work, you can directly setState inside getSearchData() like:如果这也不起作用,您可以直接在 getSearchData() 中设置状态,例如:

function getSearchData(searchTerm) {
   flaskRoute("/api/search/", searchTerm).then(result => {
     setSearchData(result);
});
}

The answer is to use an asynchronous function in the file that has the React useState/setState function and any other function in between.答案是在具有 React useState/setState function 和任何其他 function 的文件中使用异步 function。 Keep in mind that the useState hook is asynchronous itself.请记住,useState 挂钩本身是异步的。

async function regularRoute({ route, searchTerm = '', method = 'GET' }) {
    const routeWithSearchTerm = `${route}/${searchTerm}`;
    const endpoint = `${HOST_IP_ADDRESS}${routeWithSearchTerm}`;
    const configs = {
        method,
        mode: 'cors',
        headers: { 'Content-Type': 'application/json' },
    };

    return fetch(endpoint, configs)
        .then(res => res.json())
        .then(data => data)
        .catch((err) =>  console.error(err));
}

async function getSearchData(searchTerm) {
   const data = await flaskRoute('/api/search/', searchTerm);
   return data;
}

Then in my React file:然后在我的 React 文件中:

import React, { useState } from 'react';

const [data, setData] = useState('');

async function handleClick(e, searchTerm) {
    e.preventDefault();
    const newData = await getSearchData(searchTerm);
    setData(newData);
};

Done.完毕。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM