在Fetch API`then()`中使用的最新状态

欢乐

我正在使用REACT挂钩组件,该组件使用Fetch API来获取数据fetch虽然,我面临的一个问题是我不确定如何解决这个问题,或者更好地说,我不确定是否有任何“推荐”的方式来解决此问题。

以下面的代码为例:

const Fetcher = () => {
    [data, setData] = useState([]);

    const handleButtonClick = (e) => {
        fetch('http://www.myapi.com')
            .then(response => response.json())
            .then(json => {
                const newData = [...data];
                newData.push(json);

                setData(newData);
            });
    }

    return <button onClick={handleButtonClick}>Click to fetch</button>
}

这不是一个可行的示例,但是很清楚发生了什么:我单击一个按钮,然后获取东西;某些东西已添加到当前状态。

现在,问题出在哪里?当我写文章时,const newData = [...data]我考虑的datafetch启动时可用变量,而不是当前变量data这意味着,如果fetch要花1分钟执行时间,那么在那一刻data可能会以其他方式进行更新,因此,在fetch.then().then()调用时,我会data用不正确的值覆盖实际电流

我可以给您这个方案,以使您更好地理解:

  1. 我单击并首先fetch执行data等于[ ]
  2. 我在第一个fetch结尾之前再次单击(再次data等于[ ]
  3. 第二次提取结束并data保存新值(例如['foo']);
  4. 首次读取结束接收“ bar”。由于它使用的data是一个空数组,因此将其保存在data数组中['bar']

如您所见,在一天结束时,我有一个数组['bar'],而应该是['foo', 'bar']

针对此问题,我提出了两种解决方案:

  1. 将状态副本保存在中ref,并在中使用它fetch.then().then()像这样:

    const Fetcher = () => {
        [data, setData] = useState([]);
        const refData = useRef(data);
    
        const handleButtonClick = (e) => {
            fetch('http://www.myapi.com')
                .then(response => response.json())
                .then(json => {
                    const newData = [...refData.current];
                    newData.push(json);
    
                    setData(newData);
                });
        }
    
        useEffect(() => {
            refData.current = data;
        }, [data]);
    
        return <button onClick={handleButtonClick}>Click to fetch</button>
    }
    
  2. 使用一个临时变量和一个useEffect来处理最新的变量:

    const Fetcher = () => {
        [data, setData] = useState([]);
        [lastFetchedData, setLastFetchedData] = useState();
    
        const handleButtonClick = (e) => {
            fetch('http://www.myapi.com')
                .then(response => response.json())
                .then(json => {
                    setLastFetchedData(json);
                });
        }
    
        useEffect(() => {
            const newData = [...data];
            newData.push(lastFetchedData);
    
            setData(newData);
        }, [lastFetchedData]);
    
        return <button onClick={handleButtonClick}>Click to fetch</button>
    }
    

我很确定他们两个都可以正常工作而不会造成任何重大问题,但是:

  1. 第一种方法:我不知道,在我看来这与REACT思维方式背道而驰。我正在使用ref来保持某个地方的最新状态。我的意思是,我不知道这对于REACT“生活方式”是否可行;

  2. 第二种方法:在这种情况下,我仅使用状态。我在这里不喜欢的是,每当获取一些数据时,我都会做一个额外的渲染。没什么大不了的,但是,如果可以避免,那就更好了。如果lastFetchedData不是null我可以返回一个空白页,但用户可能会在毫秒内看到该空白页。实际上,它不会看到空白页面,但是由于两个渲染,页面可能会闪烁;

TJ人群

通常的解决方案是使用以下回调形式setData

const Fetcher = () => {
    [data, setData] = useState([]);

    const handleButtonClick = (e) => {
        fetch('http://www.myapi.com')
            .then(response => response.json())
            .then(json => {
                setData(data => [...data, json]); // <============
            });
    }

    return <button onClick={handleButtonClick}>Click to fetch</button>
}

旁注:

  1. 你的代码是堕入中footgunfetch我描述API在这里您需要response.ok在致电之前进行检查json

  2. 您没有处理来自的错误fetch

  3. 您忘了声明datasetData(我建议使用严格模式,所以这是一个错误):

所以:

const Fetcher = () => {
    const [data, setData] = useState([]);
//  ^^^^^−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− #3

    const handleButtonClick = (e) => {
        fetch('http://www.myapi.com')
            .then(response => {
                if (!response.ok) {                                   // #1
                    throw new Error("HTTP error " + response.status); // #1
                }                                                     // #1
                return response.json();
            })
            .then(json => {
                setData(data => [...data, json]);
            })
            .catch(error => {                                         // #2
                // Handle/report error here                           // #2
            });                                                       // #2
    }

    return <button onClick={handleButtonClick}>Click to fetch</button>
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

在Fetch API响应中使用promise仍会使我的数据返回未定义状态

来自分类Dev

使用 fetch API 授权

来自分类Dev

在React Compnent中使用Fetch

来自分类Dev

在重构代码中使用 fetch

来自分类Dev

在 Javascript 中使用 fetch API 接收和处理 JSON

来自分类Dev

在 React JS 中使用 Fetch 获取 API 数据

来自分类Dev

'BAD REQUEST' 在 JavaScript 中使用 Fetch 方法调用 API 时

来自分类Dev

在 javascript 中使用 fetch 请求 API 有 CORS 策略错误

来自分类Dev

使用Fetch API访问JSON

来自分类Dev

尝试使用早期 api fetch 中的 id 进行 api fetch

来自分类Dev

从窗口获取路径名并将其存储在状态以在 fetch 函数中使用

来自分类Dev

使用fetch()返回HTML

来自分类Dev

使用fetch()Webapi

来自分类Dev

使用fetch()Webapi

来自分类Dev

无法在React Native中使用`fetch()`

来自分类Dev

在MySQLi_fetch_assoc中使用foreach

来自分类Dev

在Meteor中的函数中使用.find()。fetch()

来自分类Dev

在 Identity Server 4 中使用 fetch

来自分类Dev

无法在 React 中使用 fetch 获得响应

来自分类Dev

使用 Promise.all 和 fetch API 返回的数据动态设置状态对象:React+Typescript

来自分类常见问题

使用Fetch API读取响应标头

来自分类Dev

无法使用JavaScript Fetch API发布数据

来自分类Dev

使用Fetch API时的“结果”是什么?

来自分类Dev

使用 fetch api 读取 .scss 文件

来自分类Dev

使用 Fetch API 邮寄表单数据

来自分类Dev

使用 fetch 和方法 get 调用 Api

来自分类Dev

如何使用 JEST 测试 fetch API 类?

来自分类Dev

使用 Fetch Api 进行 Giphy 搜索

来自分类Dev

使用 JS Fetch API 的 PHP POST