Я использую Twitter API с Javascript API для веб-сайтов. Когда я нажимаю на тег привязки, который должен перенаправить на / twitter / explore from / twitter, я перенаправляюсь на / 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.
Я пытаюсь решить эту проблему, добавив глобальную переменную и вызывая setState, только когда эта переменная равна true, а позже, когда компонент отключается, я изменяю переменную на 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);
с AOC 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;