Twitter API:警告:无法在已卸载的组件上执行React状态更新

时间:2019-10-12 15:12:00

标签: javascript reactjs twitter widget

我将twitter API与Jav​​ascript 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;

0 个答案:

没有答案