【问题标题】:React-native - screen on iOS is not updated even if render method is calledReact-native - 即使调用渲染方法,iOS 上的屏幕也不会更新
【发布时间】:2025-11-25 12:40:01
【问题描述】:

我正在开发移动应用程序,但遇到了不知道如何解决的问题。

创建屏幕后,我必须从 API 加载一些数据。我在componentDidMount 方法中执行此操作,即async,因此我可以使用await 关键字。之后,我设置状态,因此 Loader 组件(只是显示文本的模式)被隐藏,屏幕使用来自 API 的数据重新呈现。这在 Android 设备上运行良好。但是在 iOS (iPhone X) 上运行此代码不起作用。 SomeScreen.jsLoader.js 的渲染方法被调用,Loader.js 渲染方法返回 null(用控制台检查)但 iPhone 上的视图没有更新。即使它的渲染方法返回 null,加载器模式仍然存在。我做错什么了吗?致电this.foceUpdate() 也无济于事。

SomeScreen.js

import React, {Component} from 'react';
import Loader from 'components/Loader/Loader';

export default class SomeScreen extends Component {

    constructor(props) {
        super(props);
        this.state = {
            loading: true,
            data: []
        };
    }

    async componentDidMount() {
        const data = await this.loadData();
        this.setState({loading: false, data: data})
    }

    async loadData() {
       //fetch and return data from API
    }

    render() {
        return (
            <SafeAreaView style={{flex: 1}}>
                <Loader loading={this.state.loading}/>
                //other rendering...
            </SafeAreaView>
        );
    }
}

Loader.js

import React, {Component} from 'react';
import {Modal, Text, View} from 'react-native';

export default class Loader extends Component {
    static defaultProps = {
        loading: false
    };

    render() {
        if (this.props.loading !== true) {
           return null;
        }
        return(
          <Modal
              transparent={false}
              animationType={'none'}
              visible={true}>
            <View style={{backgroundColor: "white", flex: 1, justifyContent: "center"}}>
              <Text>Loading data...</Text>
            </View>
          </Modal>
        )
    }
}

【问题讨论】:

    标签: ios reactjs react-native render setstate


    【解决方案1】:

    我不确定您为什么会看到 iOS 和 Android 之间的差异,但我认为您可以尝试简化 Loader 组件的渲染方法。这样您就可以避免使用 2 个return 调用。

    import React, {Component, Fragment} from 'react';
    
    render() {
      return (
          <Fragment>
            {this.props.loading ? null : {
             <Modal
               transparent={false}
               animationType={'none'}
               visible={this.props.loading}>
                <View style={{backgroundColor: "white", flex: 1, justifyContent: "center"}}>
                  <Text>Loading data...</Text>
                </View>
              </Modal>
            }
          </Fragment>
        )
    }
    

    上面的代码检查loading 属性并加载Modal 组件,或者什么都不做。我还将 this.props.loading 道具作为值添加到您的模态的 visible 道具中。我认为这可能已经丢失了。

    【讨论】:

      【解决方案2】:

      嗯,终于找到答案了。这是因为即使我将animationType 设置为none,iOS 上的模态上也有打开动画。而如果我把loading改成false,在这个动画被钓到之前,modal还是打开的。动画大约需要 550 毫秒,我的 API 调用大约需要 200 毫秒。

      Loader.js

      import React, {Component} from 'react';
      import {Modal, Text, View} from 'react-native';
      
      export default class Loader extends Component {
          static defaultProps = {
              loading: false
          };
      
          constructor(props) {
              super(props);
              this.state = {
                  loading: props.loading
              };
          }
      
          componentWillReceiveProps(nextProps, nextContext) {
              if (this.state.loading === true && nextProps.loading === false) {
                  setTimeout(() => {
                      this.setState({loading: false});
                  }, 600);
              }
              if (this.state.loading === false && nextProps.loading === true) {
                  this.setState({loading: true});
              }
          }
      
          render() {
              if (this.state.loading !== true) {
                 return null;
              }
              return(
                <Modal
                    transparent={false}
                    animationType={'none'}
                    visible={this.state.loading}>
                  <View style={{backgroundColor: "white", flex: 1, justifyContent: "center"}}>
                    <Text>Loading data...</Text>
                  </View>
                </Modal>
              )
          }
      }
      

      基本上,在我的解决方案中,我确保模态以 600 毫秒的延迟关闭,以便有时间完成其弹出动画。

      【讨论】: