首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >无法在react中设置已卸载组件的状态

无法在react中设置已卸载组件的状态
EN

Stack Overflow用户
提问于 2019-01-28 13:55:49
回答 2查看 525关注 0票数 1

我对react和redux还不熟悉。下面是我正在做的事情:

我有一个组件,就像,

代码语言:javascript
复制
class LandingPage extends React.Component {

  constructor(props) {
    super(props);
    this.state = {
      isloading: true
    }
  }

  componentDidMount() {
    this.props.fetchJobDescription().then(() => {
      this.setState({
        isloading: false
      })
    });
  }

render() {
    if (this.state.isloading) {
      return null;
    }
    else if (this.props.jobs && this.props.jobs.content && this.props.jobs.content.length > 0) {
      return <JobList />;
    }
    else if (this.props.isError) {
      return <ErrorComponent />
    }
    else {
      return <Redirect to="/create-job" />
    }
  }
}

动作是这样的,

代码语言:javascript
复制
export function fetchUserJd() {
  return (dispatch) => {
    let url = FETCH_JD_ROOT_URL + page + "&" + size;
    dispatch({
      type: REQUEST_INITIATED
    })
    return get(url)
      .then((response) => {
        if (response.status === 200) {
          dispatch({
            type: FETCHING_JOBDESCRIPTION_SUCCESS,
            data: response.payload
          })
          dispatch({
            type: REQUEST_SUCCESSED
          })
        } else {
          if (!response.status) {
            toastr.error('Our server is down. Please check again');
          }
          else if (response.status.status === 401) {
            dispatch(logout());
          }
          else if (response.status.status === 500) {
            toastr.error("Error while Fetching the job description,Please try again");
            dispatch({
              type: FETCHING_JOBDESCRIPTION_SUCCESS,
              data: response.status,
            });
            dispatch({
              type: REQUEST_SUCCESSED
            })
          } else {
            dispatch({
              type: REQUEST_SUCCESSED
            })
          }
        }
      })
    return Promise.resolve();
  }
};

现在,我的注销是,

代码语言:javascript
复制
export function logout() {
    console.log("calling the logout action");
    localStorage.clear();
    history.push('/login');
    return {
        type: LOGOUT_REQUEST
    }
}

class Header extends React.Component {

  constructor(props) {
    super(props);
  }

  logout = (e) => {
    e.stopPropagation();
    e.nativeEvent.stopImmediatePropagation();
    e.preventDefault();
    this.props.logout();
  }


  render() {
    return (
      <Fragment>
        <Navigation
          isAuthenticated={localStorage.getItem("access_token") ? true : false}
          operationType={this.props.operationType}
          logout={this.logout} />
      </Fragment>
    )
  }
}

const mapStateToProps = (state) => {
  return {
    isAuthenticated: state.LoginReducer.isAuthenticated,
    operationType: state.Header.operationType,
  }
}

在这里,当有一个无效的令牌时,比如在获取它时,我给了我401个未经授权的令牌,然后我重定向使用注销操作。现在,

当我这样做的时候,我得到了一个错误:

代码语言:javascript
复制
Warning: Can't perform a React state update 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.
    in LandingPage (created by Context.Consumer)
    in Connect(LandingPage) (created by Route)

如何解决此错误?

EN

回答 2

Stack Overflow用户

发布于 2019-01-28 14:05:47

这是发生在你的代码中的一个小问题。当您收到401令牌时,您尝试使用history.push从操作创建器中重定向到注销,这将卸载您的LandingPage组件,但同时您正在尝试使用loading: false进行setState,因此您将收到此警告。解决方案很简单

代码语言:javascript
复制
class LandingPage extends React.Component {

  constructor(props) {
    super(props);
    this.state = {
      isloading: true
    }
    this._mounted = true;
  }

  componentDidMount() {
    this.props.fetchJobDescription().then(() => {
      if (this_mounted) {
         this.setState({
           isloading: false
         }) 
      }
    });
  }

  componentWillUnmount() {
     this._mounted = false;
  }
render() {
    if (this.state.isloading) {
      return null;
    }
    else if (this.props.jobs && this.props.jobs.content && this.props.jobs.content.length > 0) {
      return <JobList />;
    }
    else if (this.props.isError) {
      return <ErrorComponent />
    }
    else {
      return <Redirect to="/create-job" />
    }
  }
}

或者,在操作创建器中,您可以抛出错误,而不是分派注销操作,然后在fetchJobDescription.catch块中分派注销操作

在LandingPage中

代码语言:javascript
复制
this.props.fetchJobDescription().then(() => {
       this.setState({
           isloading: false
       }) 
    }).catch((err) => {
        this.props.logout();
    });

在行动中的创造者

代码语言:javascript
复制
  else if (response.status.status === 401) {
        throw new Error('Error in status')
  }
票数 0
EN

Stack Overflow用户

发布于 2019-01-28 14:06:45

该问题是因为您在卸载组件后设置状态。问题可能是你让api命中,组件卸载,然后返回设置状态的api的响应。如果您使用的是axios,那么它可以是handled

代码语言:javascript
复制
// in the component
signal = axios.CancelToken.source();
// in componentWillUnmount
this.signal.cancel('API was cancelled');
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54396251

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档