我是React和Redux的新手。这是我在做什么:
我有一个类似的组件,
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" />
}
}
}
动作就像,
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();
}
};
现在,我的注销是,
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未经授权时,我将重定向用于注销操作。现在,
当我这样做的时候,我得到一个错误:
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)
如何解决此错误?
答案 0 :(得分:0)
这是您的代码中发生的一个小问题。收到401令牌时,您尝试使用history.push从操作创建者中重定向到注销,这将卸载LandingPage组件,但与此同时,您尝试使用setState
loading: false
,因此您会收到此警告。解决方法很简单
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" />
}
}
}
或者在动作创建器中,您可以抛出错误而不是调度注销动作,并且在.catch
的{{1}}块中调度注销动作
在LandingPage中
fetchJobDescription
以及行动创建者
this.props.fetchJobDescription().then(() => {
this.setState({
isloading: false
})
}).catch((err) => {
this.props.logout();
});
答案 1 :(得分:0)
问题是因为在卸载组件后正在设置状态。问题可能是您使api命中,卸载了组件,然后返回api的响应并设置了状态。如果您使用的是axios,则可以为handled。
// in the component
signal = axios.CancelToken.source();
// in componentWillUnmount
this.signal.cancel('API was cancelled');