Android React Native:setState in finally()

Android React Native:setState in finally(),android,react-native,ecmascript-6,fetch-api,Android,React Native,Ecmascript 6,Fetch Api,我在“render()”方法中使用以下代码启用/禁用网络活动指示器: 在“fetch()之前”和 在“.finally()”中,如下所示: this.setState({networkActivity: true}); fetch(...) .then(...) .catch(...) .finally(this.setState({networkActivity: false})); this.setState({networkActivity: true}); const returnVa

我在“render()”方法中使用以下代码启用/禁用网络活动指示器:

在“fetch()之前”和

在“.finally()”中,如下所示:

this.setState({networkActivity: true});
fetch(...)
.then(...)
.catch(...)
.finally(this.setState({networkActivity: false}));
this.setState({networkActivity: true});
const returnValueOfSetState = this.setState({networkActivity: false});

fetch(...)
.then(...)
.catch(...)
.finally(returnValueOfSetState);
指示灯根本不显示。知道为什么吗

将“this.setState({networkActivity:false})”移动到“.then()”或“.catch()”块可以解决问题(作为解决方法)。指示灯亮了


在安卓6设备上测试。React本机版本:0.51

由于fetch是一种web标准,因此它使用了大多数web浏览器可用的标准Promise API。这意味着“Finally”方法不存在

我相信这些都是可用的方法。您可以创建自己的Finally方法并将其作为Promise.resolve()调用,以完成承诺链

但是,如果该方法可用,则需要调用括号内的函数

// incorrect -> ...finally(setState...)
// correct -> ...finally(function(){ this.setState() /* this might not be scoped properly here */ })
// correct -> ...finally(()=>this.setState())

finally
,比如
then
catch
接受一个函数,在您的示例中,您提供了
this.setState()
finally
的返回值

两个
setState
调用都会立即运行

基本上,您拥有的代码在功能上大致如下:

this.setState({networkActivity: true});
fetch(...)
.then(...)
.catch(...)
.finally(this.setState({networkActivity: false}));
this.setState({networkActivity: true});
const returnValueOfSetState = this.setState({networkActivity: false});

fetch(...)
.then(...)
.catch(...)
.finally(returnValueOfSetState);
这意味着您将
networkActivity
设置为
true
,然后立即将其设置回
false
。然后当
最终发生时
会尝试执行
returnValueOfSetState
,我认为这是
未定义的
,所以这是不可行的

这只是语法上的一个错误,您实际上想要的是:

this.setState({networkActivity: true});

fetch(...)
.then(...)
.catch(...)
.finally(() => {
  this.setState({networkActivity: false});
});

React Native的fetch中不支持
finally
。但是核心团队计划很快改变fetchpolyfill(),这可能会解决这个问题

如果你想改变,这里是你可以做的

重写
fetch
函数,以注入网络活动加载器

const globalFetch = global.fetch;

global.fetch = (url: string, params: Object): Promise<*> => {
  return new Promise((resolve: any => void, reject: string => void) => {
    StatusBar.setNetworkActivityIndicatorVisible(true);

    // TODO: use Promise.finally with RN >= 0.60
    globalFetch(url, params)
      .then((response: any) => {
        resolve(response);
        StatusBar.setNetworkActivityIndicatorVisible(false);
      })
      .catch((error: any) => {
        reject(error);
        StatusBar.setNetworkActivityIndicatorVisible(false);
      });
  });
};
const globalFetch=global.fetch;
global.fetch=(url:string,params:Object):Promise=>{
返回新承诺((解析:any=>void,拒绝:string=>void)=>{
StatusBar.SetNetworkActivityIndicator可视(true);
//TODO:使用Promise.finally,RN>=0.60
全局蚀刻(url,参数)
。然后((响应:任意)=>{
决心(回应);
StatusBar.SetNetworkActivityIndicator可视(false);
})
.catch((错误:任意)=>{
拒绝(错误);
StatusBar.SetNetworkActivityIndicator可视(false);
});
});
};

有趣的是,当我将它更改为
时,最后(()=>this.setState({networkActivity:false}))
它就工作了!!迷茫…好发现!我更新了我的答案以反映您的评论。似乎“.finally()”现在在规范中,可能会成为标准的一部分,但另一方面,我的“巴贝尔”似乎已经理解了它。
this.setState({networkActivity: true});

fetch(...)
.then(...)
.catch(...)
.finally(() => {
  this.setState({networkActivity: false});
});
const globalFetch = global.fetch;

global.fetch = (url: string, params: Object): Promise<*> => {
  return new Promise((resolve: any => void, reject: string => void) => {
    StatusBar.setNetworkActivityIndicatorVisible(true);

    // TODO: use Promise.finally with RN >= 0.60
    globalFetch(url, params)
      .then((response: any) => {
        resolve(response);
        StatusBar.setNetworkActivityIndicatorVisible(false);
      })
      .catch((error: any) => {
        reject(error);
        StatusBar.setNetworkActivityIndicatorVisible(false);
      });
  });
};