簡體   English   中英

如何修復“無法在未安裝的組件上執行React狀態更新。” React Native中的錯誤

[英]How to fix “Can't perform a React state update on an unmounted component.” error in React Native

我在本地數據庫(sqlite)中獲取數據並更新狀態,並且出現此錯誤:

無法在已卸載的組件上執行React狀態更新。 這是> no-op,但表示您的應用程序中發生內存泄漏。 要修復,請> componentWillUnmount方法取消所有預訂和異步任務。

沒有解決方案對我有幫助。


_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(res.rows.length > 0){
                    rows = [];
                    for(let i=0; i<res.rows.length;i++){
                        rows.push(res.rows.item(i));
                    }
                    this.setState({years: rows}, {loadingData: false});
                }
            }
        )
      })
    }

  }

  componentDidMount(){
    this._isMounted = true;
    this.getYears();
  }

  render() {
    const state = this.state;
    if(!state.loadingData){
      const pickerItens = state.years.map((record, index) => {
        <Picker.Item 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{
      <Text> Loading... </Text>
    }
  }

每當有任何任務在運行時,您通過向后導航來拉開屏幕,

出現此警告,

您無需擔心任何事情。

這是正常警告。

假設您已完成setState的運行,然后卸載了所有內容。 因此,這里系統會認為我正在執行setState但是我沒有類,此或/和變量來執行此操作。

因此,它只是警告您所有內容均已卸載,而我無法在已卸載的組件上執行此操作。

關於殺死異步任務...,

假設您將計時器設置為1分鍾,並且每1分鍾對狀態變量進行一次setState設置。

let this.timerState = setTimeout(() => {
  this.setState({ timer: this.state.timer + 1 });
}, 1000);

現在,無論您做什么,這一分鍾的計時器將無限期運行,直到您終止應用程序。

因此,系統建議您在卸載組件時取消此類任務。

因此,對生命周期方法componentWillunmount進行clearTimeout(this.timerState)

因此,不要擔心警告沒有泄漏的內容。

在構造函數中初始化db並將其添加到state,如下所示:

constructor(props: Props) {
  super(props);

 const db = SQLite.openDatabase({
      name: 'test.db',
      location: 'default',
      createFromLocation: '~my_finances.db',
    },
    () => {},
    error => {
      console.log(error);
    }
  );

  this.state = {
      db,
      slug: "",
      value: "",
      cod_year: "",
      months: [],
      years: [],
      loadingData: true,
  };
}

然后在componentDidMount上進行getYears,如下所示:

getYears = () => {
   const { loadinData, db } = this.state
   if(loadingData){
      db.transaction((txn) => {
        txn.executeSql(
           "SELECT cod, slug FROM year",
           [],
           (tx, res) => {
               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});
               }
           })
       })
    }
 }

componentDidMount() {
   this.getYears();
}

只需按以下步驟關閉componentWillUnMount上的連接即可:

componentWillUnmount() {
    const { db } = this.state;
    db.close();
}

希望對您有幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM