【问题标题】:How can I prevent a componentDidMount from running, before my webservice call finishes在我的 web 服务调用完成之前,如何防止 componentDidMount 运行
【发布时间】:2019-07-24 04:30:50
【问题描述】:

当应用启动时,SplashScreen 就会出现。在 splashScreen 后面我想从缓存中获取用户名和密码,然后调用 webservice。 但是当我从componentWillMount 中的AsyncStorage.getItem('myKey') 之类的缓存中获取数据时,它会开始渲染。它不会让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
        }
      })
    }

这是我调用 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
    }

【问题讨论】:

  • 这很简单,你必须使用两个组件。父组件将加载数据,然后仅在加载数据时显示子组件。以某种方式延迟componentDidMount 的整个前提是有缺陷的,并且行不通。但是,查看您的代码,您甚至似乎不想做一些应该在组件中的事情。

标签: reactjs react-native promise fetch


【解决方案1】:

你可能想在这里使用异步方法,因为 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

【讨论】:

    【解决方案2】:

    鉴于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  
      });
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-08-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多