首页 > 解决方案 > 我能找出这个错误的真正原因吗?(反应原生)

问题描述

首先我为我的英语道歉。我已经在 React to native 应用程序上工作了 4 个月。但有时我会收到此错误并且不介意。

警告:无法对未安装的组件执行 React 状态更新。这是一个空操作,但它表明您的应用程序中存在内存泄漏。要修复,请取消 %s.%s 中的所有订阅和异步任务,在 CustomerDetailScreen 中的 componentWillUnmount 方法(在 SceneView.tsx:123)

这是因为当我单击按钮时,我会打开一个屏幕,而当屏幕未完全加载时,我会按返回按钮。如何解决此警告?我将向您展示一些示例代码示例。

我希望我能解释一下。你能帮我解决这个话题吗?我想完全理解其中的逻辑。我在一些文章中读过一些名为 AbortController 的东西,但我并不确切知道。

constructor(props) {
    super(props);
    this._isMounted = false;
    this.state = {
        id: props.route.params.id,
        username: '',
        token: null,
        cityId: 1,
        townId: 1,
        cityData: [],
        townData: [],
        selectedIndex: 0,
        selectedCity: new IndexPath(0),
        selectedTown: new IndexPath(0),
    }
}

componentDidMount() {
    this._isMounted = true;
    this._isMounted && this._getToken();
}

componentWillUnmount() {
    this._isMounted = false;
}

_getToken = async () => {        
    try {
      const username = await AsyncStorage.getItem('username');
      const token = await AsyncStorage.getItem('token');

      if(token === null) {
        await AsyncStorage.removeItem('token');
      }else {
        this.setState({ username: username, token: token });
        this._isMounted && this.loadCustomerDetail();
      }
    } catch (error) {
        console.log(error);
    }
};

loadCustomerDetail() {
    try {
        const { username, token } = this.state;

        if(token) {
            const { id } = this.state;

            var credentials = Base64.btoa(username + ':' + token);
            var URL         = `https://portal.xxxxxx.com/api/v1/Customer/${id}`;
                
            axios.get(URL, {headers : { 'Espo-Authorization' : credentials }})
            .then(this.dataSuccess.bind(this))
            .catch(this.dataFail.bind(this));                
        }
    }catch (err) {
        console.log(err);
    }
};

dataSuccess(response) {
    this.setState({
        isLoading: false,
        cityId: response.data.cityId,
        townId: response.data.townId
    }, () => {
        this.getCities();
    });
}

getCities() {
    const { username, token, cityId } = this.state;

    let credentials = Base64.btoa(username + ':' + token);

    axios.get('https://portal.xxxxx.com/api/v1/Cities', { headers : { 'Espo-Authorization' : credentials }})
    .then((response) => {
            response.data.list.sort(function(a, b) {
                return Number(a.id) > Number(b.id);
            });
            
            this.setState({cityData: response.data.list}, () => {
                this.setState({ selectedCity: new IndexPath(this.state.cityData[cityId-1].id - 1) });
                this.getTowns(this.state.cityData[cityId-1].id);
            });
        }).catch((error) => {
            console.log(error);
        });
}

getTowns(cityId) {
    this.setState({ townLoading: true });

    const { username, token } = this.state;

    let credentials = Base64.btoa(username + ':' + token);

    axios.get(`https://portal.xxxxx.com/api/v1/Towns/action/TownList?cityId=${cityId}`, { headers : { 'Espo-Authorization' : credentials }})
      .then((response) => {
            this.setState({ townData: response.data, townLoading: false }, () => {
                for (const [key, value] of Object.entries(this.state.townData)) {
                    if(value.id === this.state.townId) {
                        this.setState({ selectedTown: new IndexPath(key) })
                    }
                }
            });                
        }).catch((error) => {
            console.log(error);
        });
}

标签: javascriptreactjstypescriptreact-native

解决方案


示例区域:

this.setState({ username: username, token: token });
this._isMounted && this.loadCustomerDetail();

您可以看到setState即使不再安装组件也会调用它。

使固定

确保在更改状态之前安装组件:

if (this._isMounted) {
  this.setState({ username: username, token: token });
  this.loadCustomerDetail();
}

推荐阅读