You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React+Redux登录后自动切换组件失效问题求助

Let's work through why your component isn't switching automatically after login and fix it step by step.

What's Going Wrong

Let's break down the key issues in your current code:

  1. Mismatched state types & incorrect checks: Your reducer initializes user as an empty array [], but sets it to a token string on login success. In componentWillReceiveProps, you check nextProps.user.length — while strings do have a length property, this creates confusion, and you don't need to rely on Chrome Storage right after login (Redux already has the token once login succeeds).
  2. Redundant local state: Maintaining hasToken in your parent component creates a second source of truth separate from Redux, which leads to sync issues when Redux updates but your local state doesn't catch it properly.
  3. Outdated lifecycle method: componentWillReceiveProps is deprecated in React. Even if you needed to sync state from props, componentDidUpdate is the modern replacement.

Fixed Solution

Let's rewrite the code to fix these issues:

Step 1: Clean Up the Reducer

First, fix the initial state to avoid type confusion (use null instead of an array for user):

const initialState = {
  fetching: false,
  error: null,
  user: null // Changed from empty array to null
}

function loginReducer(state=initialState, action) {
  switch (action.type) {
    case LOGIN:
      return {...state, fetching: true}
    case LOGIN_SUCCESS:
      return {...state, fetching: false, user: action.data.access_token}
    case LOGIN_FAILURE:
      return {...state, fetching: false, error: action.error, user: null} // Reset user on failure
    default:
      return state;
  }
}

Step 2: Simplify the Parent Component

Remove the redundant local state dependency and use Redux as your single source of truth. We'll only use Chrome Storage for persistence after page refreshes:

const mapStateToProps = state => { 
  return { 
    userToken: state.loginReducer.user,
    isFetching: state.loginReducer.fetching
  } 
}

class App extends React.Component {
  state = { storedToken: null }

  componentDidMount() {
    // Check Chrome Storage only for initial page load (refresh scenario)
    window.chrome.storage.sync.get(['user_token'], result => {
      if (result.user_token) {
        this.setState({ storedToken: result.user_token })
      }
    })
  }

  componentDidUpdate(prevProps) {
    // Sync new token to Chrome Storage when Redux updates
    if (prevProps.userToken !== this.props.userToken && this.props.userToken) {
      window.chrome.storage.sync.set({user_token: this.props.userToken})
    }
  }

  anotherComponent() {
    return (
      <div className="content">
        component to show when the user logs in
      </div>
    )
  }

  render() {
    // Check both Redux state and stored token for login status
    const isLoggedIn = !!this.props.userToken || !!this.state.storedToken;
    const { isFetching } = this.props;

    return (
      <div>
        <Header />
        {isFetching ? (
          <div>Logging in...</div>
        ) : (
          !isLoggedIn ? <Login /> : this.anotherComponent()
        )}
      </div>
    )
  }
}

export default connect(mapStateToProps, null)(App);

Step 3: Ensure Your Login Action Works Correctly

Make sure your login action creator properly fetches the token and dispatches loginSuccess (assuming you're using redux-thunk or similar middleware):

export const login = (userData) => async (dispatch) => {
  dispatch({ type: LOGIN });
  try {
    const response = await fetch('/your-login-api-endpoint', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(userData)
    });
    const data = await response.json();
    dispatch(loginSuccess(data)); // data should contain the access_token
  } catch (error) {
    dispatch(loginFailure(error.message));
  }
}

Key Improvements

  • Single Source of Truth: Redux holds the login state immediately after success, with Chrome Storage only used for persistence.
  • Modern Lifecycle: Uses componentDidUpdate instead of the deprecated componentWillReceiveProps to react to prop changes.
  • Clearer State Checks: No more confusion between arrays and strings for user data.
  • Loading Feedback: Added a loading state so users know the login is in progress.

内容的提问来源于stack exchange,提问作者justforp basnet

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 09:53:51