You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Native中‘无法在已卸载组件更新状态’错误修复求助

解决React Native中SQLite异步操作后更新卸载组件状态的警告

先梳理你代码里的几个核心问题,这些正是导致警告和_isMounted标志无效的原因:

1. setState的第二个参数使用错误

你这段代码的写法有问题:

this.setState({years: rows}, {loadingData: false});

setState的第二个参数是回调函数,不是状态对象。所以loadingData: false根本没生效,你的loadingData会一直保持true——这不仅会让组件一直卡在加载状态,还会导致getYears重复执行(因为你判断了if(this.state.loadingData)),进一步加剧状态更新的问题。

正确写法应该把loadingData放到第一个参数的状态对象里:

this.setState({ years: rows, loadingData: false });

2. _isMounted标志没有在异步回调中检查

SQLite事务是异步操作,当组件卸载后,这个回调仍然会执行,但你没有在回调里检查_isMounted的状态,所以还是会触发setState,导致警告。

修改getYears,在执行setState前先判断组件是否还挂载:

getYears = () => {
  if (this.state.loadingData) {
    this.db.transaction((txn) => {
      txn.executeSql(
        "SELECT cod, slug FROM year",
        [],
        (tx, res) => {
          // 先检查组件是否仍挂载,已卸载则直接返回
          if (!this._isMounted) return;
          
          if (res.rows.length > 0) {
            // 声明rows为局部变量,避免全局污染
            let rows = [];
            for (let i = 0; i < res.rows.length; i++) {
              rows.push(res.rows.item(i));
            }
            this.setState({ years: rows, loadingData: false });
          } else {
            // 没有数据的情况也要更新loading状态
            this.setState({ loadingData: false });
          }
        }
      );
    });
  }
};

3. 组件卸载时标记_isMounted为false

必须在componentWillUnmount里更新标志,确保异步回调能感知到组件已卸载:

componentWillUnmount() {
  this._isMounted = false;
}

4. render方法的else分支缺少return

你当前的else分支只是写了<Text> Loading... </Text>,但没有return,会导致组件返回undefined,这是语法错误,需要补上:

} else {
  return <Text> Loading... </Text>;
}

5. 额外修复:Picker.Item的map函数缺少return

你的pickerItens生成逻辑里,map函数没有返回组件,导致生成的数组全是undefined,Picker里不会显示任何选项,这个也一起修正:

const pickerItens = state.years.map((record, index) => {
  return <Picker.Item key={index} label={record.slug} value={record.cod}/>
})

完整修正后的代码片段

_isMounted = false;
constructor(props) {
  super(props);
  this.state = {
    slug: "",
    value: "",
    cod_year: "",
    months: [],
    years: [],
    loadingData: true,
  };
}
db = openDatabase({ name: 'test.db', createFromLocation : '~my_finances.db'});
getYears = () => {
  if(this.state.loadingData){
    this.db.transaction((txn)=>{
      txn.executeSql(
        "SELECT cod, slug FROM year",
        [],
        (tx, res) => {
          if(!this._isMounted) return;
          if(res.rows.length > 0){
            let rows = [];
            for(let i=0; i<res.rows.length;i++){
              rows.push(res.rows.item(i));
            }
            this.setState({years: rows, loadingData: false});
          } else {
            this.setState({loadingData: false});
          }
        }
      )
    })
  }
}
componentDidMount(){
  this._isMounted = true;
  this.getYears();
}
componentWillUnmount() {
  this._isMounted = false;
}
render() {
  const state = this.state;
  if(!state.loadingData){
    const pickerItens = state.years.map((record, index) => {
      return <Picker.Item key={index} label={record.slug} value={record.cod}/>
    })
    return (
      <View style={{flex: 1}} >
        <ScrollView style={styles.container}>
          <View style={styles.form_add}>
            <Text style={styles.form_slug} > Adicionar </Text>
            <TextInput placeholder="Digite o mês..." onChangeText={(slug) => { this.setState({slug}) }} value={this.state.slug} style={styles.input_add} />
            <TextInput placeholder="Digite o valor..." onChangeText={(value) => { this.setState({value}) }} value={this.state.value} style={styles.input_add} />
            <Picker onValueChange = {(cod_year) => {this.setState({cod_year})}}>
              { pickerItens }
            </Picker>
            <Button color="#7159C1" title="Salvar" onPress={() => this.addYear()} />
          </View>
        </ScrollView>
        <Footer navigate={this.props.navigation.navigate} />
      </View>
    );
  }else{
    return <Text> Loading... </Text>
  }
}

这些修改应该能彻底解决状态更新的警告,同时修复代码里的其他隐性问题。

内容的提问来源于stack exchange,提问作者Showtime

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 07:47:56