Как отменить все подписки и асинхронные вычисления в методе componentWillUnmount? - PullRequest
0 голосов
/ 28 августа 2018

Я получаю сообщение об ошибке из-за проблемы с асинхронным методом. В моем терминале я вижу:

Warning: Can't call setState (or forceUpdate) on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in the componentWillUnmount method.
- node_modules/fbjs/lib/warning.js:33:20 in printWarning
- node_modules/fbjs/lib/warning.js:57:25 in warning
- node_modules/react-native/Libraries/Renderer/ReactNativeRenderer-dev.js:12196:6 in warnAboutUpdateOnUnmounted
- node_modules/react-native/Libraries/Renderer/ReactNativeRenderer-dev.js:13273:41 in scheduleWorkImpl
- node_modules/react-native/Libraries/Renderer/ReactNativeRenderer-dev.js:6224:19 in enqueueSetState
- node_modules/react/cjs/react.development.js:242:31 in setState
* router/_components/item.js:51:16 in getImage$
- node_modules/regenerator-runtime/runtime.js:62:44 in tryCatch
- node_modules/regenerator-runtime/runtime.js:296:30 in invoke
- ... 13 more stack frames from framework internals

Я заметил, что он конкретно указывает на getImage$

Вот код, который я использую для этого раздела:

export default class extends Component {
    constructor(props) {
        super(props);
        const { item } = props

        const bindThese = { item }
        this.boundActionCreators = bindActionCreators(bindThese)

        this.state = {
            image: require('../../static/logo.png'),
            ready: false,
            showOptions: this.props.showOptions
        }

        this.getImage = this.getImage.bind(this)
        this.renderNotAdmin = this.renderNotAdmin.bind(this)
        this.renderAdmin = this.renderAdmin.bind(this)
        this.handleOutOfStock = this.handleOutOfStock.bind(this)
    }

    async getImage(img) {
        let imgUri = await Amplify.Storage.get(img)
        let uri = await CacheManager.get(imgUri).getPath()

        this.setState({
            image: { uri },
            ready: true
        })
    }

    componentDidMount() {
        this.getImage(this.props.item.image)
    }

Я пытаюсь выяснить, как использовать componentWillUnmount с этим асинхронным методом. Как мне это сделать?

Спасибо!

Ответы [ 3 ]

0 голосов
/ 28 августа 2018

Вы можете использовать isMounted Реагировать шаблон, чтобы избежать утечек памяти здесь.

В вашем конструкторе:

constructor(props) {
    super(props);

    this._isMounted = false;
// rest of your code
}

componentDidMount() {
    this._isMounted = true;
    this._isMounted && this.getImage(this.props.item.image);

}

в вашем componentWillUnmount

componentWillUnmount() {
   this._isMounted = false;
}

Пока в тебе getImage()

async getImage(img) {
    let imgUri = await Amplify.Storage.get(img)
    let uri = await CacheManager.get(imgUri).getPath()

    this._isMounted && this.setState({
        image: { uri },
        ready: true
    })
}

Рекомендованный подход к использованию Axios , основанный на шаблоне аннулируемых обещаний. Таким образом, вы можете отменить любой сетевой вызов, размонтировав компонент с помощью cancelToken subscription. Вот ресурс для Axios Cancellation

0 голосов
/ 02 ноября 2018

Вам необходимо установить this.mounting = false в методе componentWillUnmount () и this.mounting = true в методе componentDidMount ().

Обновление setState обусловлено условной декларацией в методе componentDidMount ().

componentDidMount() {
        this.mounted = true;
        var myVar =  setInterval(() => {
                let nextPercent = this.state.percentage+10;
                if (nextPercent >= 100) {
                    clearInterval(myVar);
                }
                if(this.mounted) {
                    this.setState({ percentage: nextPercent });
            }
        }, 100);
}

componentWillUnmount(){
      this.mounted = false;
}
0 голосов
/ 28 августа 2018

Из блога React

Просто установите для свойства _isMounting значение true в componentDidMount и установите его в false в componentWillUnmount, и используйте эту переменную для проверки статус компонента.

Далее говорится, что в идеале это можно было бы исправить, используя отменяемые обратные вызовы, хотя первое решение здесь кажется подходящим.

Что вам определенно не следует делать, так это использовать функцию isMounting (), которая может быть устаревшей.

...