我将twitter API与Javascript API用于Websistes。当我单击应该从/ twitter重定向到/ twitter / explore的锚标记时,我将重定向到/ twitter / explore,但立即又回到/ twitter,这是Twitter组件。我在Chrome控制台中收到此错误:
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 twitter api.
我尝试通过添加全局变量并仅在该变量为true时才调用setState来解决此问题,然后在卸载组件时将变量更改为false。错误不存在,但应用仍将我重定向回/ twitter。因为支持我,所以无法呈现TwitterExplore组件。我不确定使用全局变量的解决方案是个好主意。
以下是我的代码:
具有/ twitter映射的Twitter组件
class Twitter extends React.Component {
isMountedTwitter = false;
constructor(props) {
super(props);
this.state = {
accessToken: '',
email: '',
name: '',
userID: '',
pictureUrl: '',
providerId: '',
screenName: '',
tokenSecret: ''
}
this.Auth = new AuthService();
}
componentDidMount() {
this.isMountedTwitter = true;
this.isMountedTwitter && window.twttr.widgets.load(document.getElementsByClassName("feed-container")[0]);
let jwtToken = null;
if(this.Auth.getTwitterToken() !== null) {
jwtToken = this.Auth.getTwitterToken();
}
if(this.Auth.getToken() !== null) {
jwtToken = this.Auth.getToken();
}
fetch(`/getuserdata/${jwtToken}`, {
method: 'GET',
headers: {
'content-type': 'application/json'
}
})
.then(response => response.json())
.then(jsonData => {
if(this.isMountedTwitter) {
this.setState({
accessToken: jsonData.accessToken,
email: jsonData.email,
name: jsonData.name,
userID: jsonData.userID,
pictureUrl: jsonData.pictureUrl,
providerId: jsonData.providerId,
screenName: jsonData.screenName,
tokenSecret: jsonData.tokenSecret
}, () => {
window.twttr.widgets.createTimeline(
{
sourceType: 'likes',
screenName: this.state.screenName
},
document.getElementsByClassName("tweets-likes-container")[0],
{
width: '100%',
height: '100%',
related: 'twitterdev,twitterapi'
});
});
}
});
}
componentWillUnmount() {
this.isMountedTwitter = false;
}
render() {
return (
<div className="twitter-container">
<div className="twitter-grid-container">
<div className="twitter-grid-item-1">
<div className="twitter-left-categories-container">
<div className="twitter-profil-container">
{ this.state.name }
</div>
<TwitterCategoriesCard
pictureUrl={this.state.pictureUrl}
screenName={this.state.screenName}
/>
</div>
</div>
<div className="feed-container">
{/* <div className="twitter-user-profil">
<div className="twitter-header-profile">
</div>
<div className="tweets-profile-container">
</div>
</div> */}
<div className="tweets-likes-container">
</div>
</div>
<div className="twitter-grid-item-3">
<div className="twitter-rl-container">
<div className="twitter-groups-container">
<SearchTwitterPeople />
<AvailableTrends />
</div>
</div>
<div className="twitter-rr-container">
<div className="twitter-friends-container"></div>
</div>
</div>
</div>
</div>
);
}
}
export default withAuth(Twitter);
TwitterCategoriesCard组件
class TwitterCategoriesCard extends React.Component {
constructor(props) {
super(props);
this.onExploreClick = this.onExploreClick.bind(this);
}
onExploreClick() {
this.props.history.push("/twitter/explore");
}
render() {
return (
<div className="twitter-categories-container">
<ul className="list-group twitter-categories-list">
<li className="list-group-item list-group-item-hover">
<div className="twitter-categories-icons-box">
<i className="fas fa-home"></i> Home
</div>
</li>
<li onClick={this.onExploreClick} className="list-group-item list-group-item-hover">
<div className="twitter-categories-icons-box">
<span style={{ fontWeight: '900' }}>#</span> Explore
</div>
</li>
<li className="list-group-item list-group-item-hover">
<div className="twitter-categories-icons-box">
<i className="fas fa-clock"></i> Timeline likes
</div>
</li>
<li className="list-group-item list-group-item-hover">
<div className="twitter-categories-icons-box">
<i className="fas fa-bell"></i> Notifications
</div>
</li>
<li className="list-group-item list-group-item-hover">
<div className="twitter-categories-icons-box">
<i className="far fa-envelope"></i> Messages
</div>
</li>
<li
className="list-group-item list-group-item-hover"
>
<div className="twitter-categories-icons-box">
<img
src={this.props.pictureUrl}
alt="Avatar"
className="twitter-categories-avatar"
/> Profile
</div>
</li>
<li className="list-group-item list-group-item-hover add-tweet-button">
<a
className="twitter-share-button"
href="https://twitter.com/intent/tweet"
data-size="large"
>
Tweet
</a>
</li>
</ul>
</div>
);
}
}
export default withRouter(TwitterCategoriesCard);
withAuth HOC:
export default function withAuth(AuthComponent) {
const Auth = new AuthService();
let customAuthComponent = false;
class AuthWrapped extends React.Component {
componentDidMount() {
customAuthComponent = true;
if(!Auth.loggedIn()) {
this.props.history.replace("/login");
} else {
let twitterJwtToken = Auth.getTwitterToken();
let facebookJwtToken = Auth.getToken();
try {
if(twitterJwtToken) {
customAuthComponent && this.props.history.replace("/twitter");
}
if(facebookJwtToken) {
customAuthComponent && this.props.history.replace("/dashboard");
}
} catch(err) {
if(twitterJwtToken) {
Auth.logoutTwitter();
}
if(facebookJwtToken) {
Auth.logout();
}
this.props.history.replace("/login");
}
}
}
componentWillUnmount() {
customAuthComponent = false;
}
render() {
if(Auth.loggedIn()) {
return (
customAuthComponent && <AuthComponent history={this.props.history} />
);
} else {
return null;
}
}
}
return AuthWrapped;
}
App.js
function App() {
return (
<Provider store={store} >
<Router>
<div className="App">
<I18nextProvider i18n={i18next}>
<Header />
<Route exact path="/settings" component={Settings} />
<Route exact path="/twitter" component={Twitter} />
<Route exact path="/twitter/explore" component={TwitterExplore} />
</I18nextProvider>
</div>
</Router>
</Provider>
);
}
export default App;