React Native:finally()中的setState

时间:2018-01-24 14:33:38

标签: android react-native ecmascript-6 fetch-api

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

{this.state.networkActivity && <NetworkActivityIndicator/>}

现在当我把

this.setState({networkActivity: true});

在“fetch()”和

之前
this.setState({networkActivity: false});

在“.finally()”中就像这样:

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

指标根本没有显示。知道为什么吗?

将“this.setState({networkActivity:false})”移动到“.then()”或“.catch()”块解决问题(作为解决方法)。指标出现。

使用Android 6在设备上测试.React Native版本:0.51

3 个答案:

答案 0 :(得分:1)

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

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise

Promise.all()
Promise.prototype.catch()
Promise.prototype.then()
Promise.race()
Promise.reject()
Promise.resolve()

我相信这些都是可用的方法。你可以创建自己的Finally方法并将其称为Promise.resolve()以完成你的Promise链。

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

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

答案 1 :(得分:0)

finally,类似于thencatch都具有一个函数,在您的示例中,您要向this.setState()提供finally的返回值。

setState的两个调用均立即运行。

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

this.setState({networkActivity: true});
const returnValueOfSetState = this.setState({networkActivity: false});

fetch(...)
.then(...)
.catch(...)
.finally(returnValueOfSetState);

这意味着您将networkActivity设置为true,然后立即将其重新设置为false。然后,当finally发生时,它会尝试执行returnValueOfSetState,我相信它是undefined,所以它是空操作。

这只是语法上的错误,您真正想要的是这样的:

this.setState({networkActivity: true});

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

答案 2 :(得分:0)

React Native的获取不支持

finally。但是核心团队计划尽快更改抓取polyfill(https://github.com/facebook/react-native/issues/23313),这可能会解决它。

如果要更改StatusBar's network activity,可以执行以下操作。

覆盖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);
      });
  });
};