javascript - 正确卸载 React 组件

标签 javascript reactjs redux react-redux

问题:为什么在组件不再由其父组件渲染后会抛出此警告?我是否缺少卸载该组件所需执行的操作,而不仅仅是过滤作为 props 沿组件层次结构传递的存储状态?

我经常看到这种情况,但解决方案通常是从组件中取消订阅 redux 存储;然而,这个组件没有连接到商店,只是顶级容器。

  • remove 操作只是过滤存储状态以删除负责当前组件的数组元素。
  • refresh 操作目前只是子组件中 UI 动画事件的模拟。
  • 仅当我在调用 refresh 操作后删除 Feed 组件时才会引发警告

Warning: setState(...): Can only update a mounted or mounting component. This usually means you called setState() on an unmounted component. This is a no-op. Please check the code for the Feed component.

// @flow
// Feed.js

import React, { Component } from 'react'
import type { FeedType, FeedState } from '../../utils/types'
import { remove, refresh } from '../../actions/redux-actions'
import RssEventList from '../containers/RssEventList'

const cardColors: Array<string> = ['red', 'orange', 'olive', 'green', 'blue', 'yellow']

export default class Feed extends Component {
  props: FeedType
  state: FeedState

  constructor(props: *) {
    super(props)

    this.state = {
      reloading: false
    }
  }

  refresh() {
    this.setState({ reloading: true })
    setInterval(() => this.setState({ reloading: false }), 4000)
    this.props.dispatch(refresh(this.props.link))
  }

  remove() {
    this.props.dispatch(remove(this.props.link))
  }

  render() {
    const color: string = cardColors[Math.floor(Math.random() * cardColors.length)]

    return (
      <div className={`ui ${color} card`}>
        <div className="content">
          <div className="ui header">
            {this.props.title}
            <a className="source link" href={this.props.link} target="_blank">
              <i className="linkify right floated icon"></i>
            </a>
          </div>
          <div className="meta">
            {this.props.description}
          </div>
        </div>
        <div className="content">
          <RssEventList reloading={this.state.reloading} events={this.props.feed} />
        </div>
        <div className="extra content">
          <span className="left floated" onClick={() => this.refresh()}>
            <i className="refresh icon"></i>
            Refresh
          </span>
          <span className="right floated" onClick={() => this.remove()}>
            <i className="cancel icon"></i>
            Remove
          </span>
        </div>
      </div>
    )
  }
}

如果有帮助的话,这里是组件层次结构图:

App (connected to store)
|- Header
|- FilterBar
|- FeedList
   |- Feed
      |- RssEventList
         |- RssEvent
   |- AddCard

最佳答案

问题是您没有将间隔存储在组件上,以便在组件卸载时将其删除。因此,即使组件被卸载后,该间隔也会继续被调用。您需要使用 clearInterval() 删除它:

export default class Feed extends Component {
  refresh() {
    this.myInterval = setInterval(() => this.setState({ reloading: false }), 4000)
  }

  componentWillUnmount() {
    clearInterval(this.myInterval);
  }
}

关于javascript - 正确卸载 React 组件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43097815/

相关文章:

javascript - 为什么在 Redux store 中使用 spread operator?

javascript - 通过 JS 正则表达式从字符串中检索数字

javascript - 如何动态更新 dropkick.js 下拉菜单中的选项?

javascript - 更改过滤器内的开始和结束索引

reactjs - 如何让源映射适用于 React Css 模块?

redux - Flutter redux thunk Action 参数

javascript - 当焦点位于其他窗口时停止运行 Javascript Web 应用程序的方法

javascript - 如何在 react 地理图表上调用点击事件?

css - '& > * + *' 在 JSX (CSS) 中意味着什么?

javascript - Redux:通用Reducer 与每个实体的Reducer