在Web服务调用完成之前,如何阻止componentDidMount运行

时间:2019-03-02 08:11:35

标签: reactjs react-native promise fetch

启动应用程序时,将启动SplashScreen。在splashScreen的后面,我想从缓存中获取用户名和密码,然后调用webservice。 但是,当我从AsyncStorage.getItem('myKey')中的componentWillMount之类的缓存中获取数据时,它将开始渲染。它不会让componentWillMount完成。

我的大问题是componentDidMount在我的controlallMeth方法完成之前开始。因此,在这种情况下应用程序崩溃。如何解决此问题?
这是我的代码:

我从应用程序缓存中获取用户名和密码,并像这样调用网络服务:

 componentWillMount(){
      AsyncStorage.getItem('myKey').then(value => {
        let valuePrsed = JSON.parse(value);
        if(valuePrsed.username != null && valuePrsed.password != null)
        {
            this.setState({username: valuePrsed.username, password: valuePrsed.password});
            this.controlallMeth(); // call webservice
        }
      })
    }

这是我调用网络服务的方法:

controlallMeth(){
        let collection={}
        collection.username = this.state.username,
        collection.password = this.state.password

        fetch('url', {
            method: 'POST',
            headers: new Headers({
                          Accept: 'application/json',
                        'Content-Type': 'application/json', // <-- Specifying the Content-Type
                }),
            body: JSON.stringify(collection) // <-- Post parameters
            })
            .then((response) => response.text())
            .then(leaders => {

                    this.setState({PersonalInfo: leaders});

            })
            .catch((error) => {
                console.error(error);
            });
    }

这是componentDidMount

 componentDidMount() {

      StatusBar.setHidden(true);
        this.setState({ fadeAnim: new Animated.Value(0) },
        () => {
          Animated.timing(          // Animate over time
            this.state.fadeAnim, // The animated value to drive
            {
              toValue: 1,           // Animate to opacity: 1 (opaque)
              duration: 3000,
            }
          ).start(() => {
              if(this.state.values != null)
              {
                console.log("go page1");
                  this.props.navigation.navigate('Page1',{datas: this.state.PersonalInfo});
              }
              else{
                this.props.navigation.navigate('login');
              }
          })
        })              // Starts the animation
    }

2 个答案:

答案 0 :(得分:1)

鉴于componentWillMount已被弃用,最好不要使用它。您可以在constructorcomponentDidMount方法中获取缓存的值

constructor(props) {
  super(props);

  StatusBar.setHidden(true);

  AsyncStorage.getItem('myKey').then(value => {
    let valuePrsed = JSON.parse(value);
    if(valuePrsed.username != null && valuePrsed.password != null)
    {
      this.setState({username: valuePrsed.username, password: valuePrsed.password});
      this.controlAllMeth(); // call webservice
    }
  });
}

要确保动画和获取方法在转到其他屏幕之前完全完成,可以使用Promise.all

controlAllMeth() {
  Promise.all([this.callFetch(), this.startAnim()])
    .then(([fetchResponse, animResponse]) => {
      this.setState({PersonalInfo: fetchResponse.text()});

      if(this.state.values != null)
      {
        console.log("go page1");
        this.props.navigation.navigate('Page1',{datas: this.state.PersonalInfo});
      }
      else{
        this.props.navigation.navigate('login');
      }
    })
    .catch(err => {

    });
}

callFetch() {
  let collection={}
  collection.username = this.state.username,
  collection.password = this.state.password

  return fetch(url, {
    method: 'POST',
    headers: new Headers({
      Accept: 'application/json',
      'Content-Type': 'application/json', // <-- Specifying the Content-Type
    }),
    body: JSON.stringify(collection) // <-- Post parameters
    }
  );
}

startAnim() {
  return new Promise((resolve, reject) => {
    this.setState({ fadeAnim: new Animated.Value(0) },
      () => {
        Animated.timing(          // Animate over time
          this.state.fadeAnim, // The animated value to drive
          {
            toValue: 1,           // Animate to opacity: 1 (opaque)
            duration: 3000,
          }
        ).start(() => {
          resolve();
        })
      });              // Starts the animation  
  });
}

答案 1 :(得分:-1)

您可能想在这里使用async方法,因为controlallMeth是一个异步调用。使整个过程等待以确保您执行了获取请求,然后继续。

async componentWillMount(){
      AsyncStorage.getItem('myKey').then(value => {
        let valuePrsed = JSON.parse(value);
        if(valuePrsed.username != null && valuePrsed.password != null)
        {
            this.setState({username: valuePrsed.username, password: valuePrsed.password});
          await this.controlallMeth(); //I am assuming you did a typo here this.controlall();
        }
      })
    }
 controlallMeth = async() => {
        let collection={}
        collection.username = this.state.username,
        collection.password = this.state.password

        const res = await fetch('url', {
            method: 'POST',
            headers: new Headers({
                          Accept: 'application/json',
                        'Content-Type': 'application/json', // <-- Specifying the Content-Type
                }),
            body: JSON.stringify(collection) // <-- Post parameters
            })
            const leaders = await res.text();
            this.setState({PersonalInfo: leaders});
    }

尽管不建议在componentWillMount中进行异步调用,所以您可能希望切换到componentDidMount