【问题标题】:How to fix "Can't perform a React state update on an unmounted component." error in React Native如何修复“无法在未安装的组件上执行 React 状态更新”。 React Native 中的错误
【发布时间】:2019-10-05 19:06:56
【问题描述】:

我正在本地数据库(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>
    }
  }

【问题讨论】:

    标签: javascript android react-native


    【解决方案1】:

    每当有任何任务正在运行并且您通过导航返回关闭屏幕时,

    出现此警告,

    您无需担心任何事情。

    这是正常警告。

    假设你已经完成了setState 它正在运行并且你卸载了所有东西。 所以这里系统会认为我在做setState 但我没有类、这个或/和变量来做它。

    所以它只是警告你所有东西都被卸载了,我不能在卸载的组件上这样做。

    关于杀死异步任务...,

    假设您设置了一个 1 分钟的计时器,并且每隔 1 分钟您在状态变量上执行setState

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

    现在无论你做什么,这个一分钟的计时器都会无限运行,直到你杀死你的应用程序。

    所以系统建议你在卸载组件时终止这种类型的任务。

    clearTimeout(this.timerState) 对生命周期方法 componentWillunmount 也是如此。

    所以不要担心警告没有什么可以泄露的。

    【讨论】:

    【解决方案2】:

    在构造函数中初始化db并将其添加到状态如下:

    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,
      };
    }
    

    然后 getYears on componentDidMount 如下:

    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();
    }
    

    希望对你有帮助。

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-11-30
    • 2020-09-03
    • 1970-01-01
    • 2022-01-18
    • 1970-01-01
    • 2023-02-11
    • 2021-11-30
    • 2020-08-03
    相关资源
    最近更新 更多