React中如何将用户登录状态传递给子组件并控制链接显示
Fixing the LoggedIn State Prop Issue Between VideoPlayer and Paywall
Let's walk through the issues in your code and fix them to get the logged-in state properly passed to the Paywall component.
Key Problems Identified
- No stored
loggedInstate: You calculate aloggedInvariable incomponentDidMountbut don’t save it to the component state, then re-calculate a similar (but error-prone) value directly in the render method. This creates inconsistencies and makes debugging harder. - Unhandled request failure edge cases: If the
/api/userrequest fails,this.state.userstays undefined, which doesn’t explicitly reflect the user’s logged-out state. - Potential race condition: If
fetchData()setsblocking: 'paywall'before the user data request completes, the Paywall might render before the logged-in state is ready.
Step-by-Step Fix
1. Update the Parent Component (VideoPlayer)
First, add loggedIn to your initial state, then calculate and set it properly when fetching user data:
class VideoPlayer extends React.Component { constructor(props) { super(props); this.state = { blocking: undefined, user: null, loggedIn: false // Default to logged-out state }; } async componentDidMount() { if (this.md.mobile()) { this.setState({ blocking: 'mobile' }); } else if (this.browser.name === 'ie' || this.browser.name === 'edge') { this.setState({ blocking: 'unsupported' }); } else { try { const userData = await superagent.get('/api/user'); if (!userData.error) { // Calculate loggedIn based on your API's response rules const loggedIn = userData.body.success === undefined; // True if user is logged in this.setState({ user: userData.body, loggedIn: loggedIn }, () => { // Ensure user state is updated before fetching additional data this.fetchData(); }); } else { // API returned an error, set loggedIn to false this.setState({ loggedIn: false }, () => this.fetchData()); } } catch (err) { console.log('Could not fetch user.', err); // Request failed, assume user is logged out this.setState({ loggedIn: false }, () => this.fetchData()); } } } render() { return ( <div className='video-player-container'> {this.state.blocking === 'paywall' && ( <Paywall bgImgUrl={this.props.imageUrl('paywall-bg.png')} logoUrl={this.props.imageUrl('logo.png')} loggedIn={this.state.loggedIn} // Pass the stored state directly {...this.props} /> )} </div> ); } }
2. Hardening the Child Component (Paywall)
Your Paywall logic is mostly correct, but adding a default prop value ensures we handle edge cases where loggedIn isn’t passed properly:
function Paywall(props) { const { iconHrefs, logoUrl, bgImgUrl, config, loggedIn = false } = props; // Add fallback value return ( <div className='blocking-paywall' style={{ backgroundImage: `url(${bgImgUrl})` }}> <div className='container'> <div className='logo'> <img src={logoUrl} /> </div> <h1 className='heading lg'>{content.heading}</h1> <div className='message'> <div className='subpara'>content</div> <div className='subpara'>catchphrase</div> </div> <div className='login'> {/* Show login link only when user is not logged in */} {!loggedIn && ( <p>already a member?<a href='/login'>Login</a></p> )} </div> </div> </div> ); }
Final Checks
- Confirm your API response: Make sure logged-in users return
success: undefinedand logged-out users returnsuccess: false— adjust theloggedIncalculation if your API’s response format changes. - Verify
fetchData(): Ensure it setsblocking: 'paywall'only after the user data is loaded (using thesetStatecallback as shown ensures this).
内容的提问来源于stack exchange,提问作者Matt
相关产品推荐
相关产品推荐

