Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ReactJS/nextJS: Don't get access to cookie/properties after redirecting

In my nextJS application the user can do a login (login page), which creates a cookie with a token and redirects to a route (main page), which uses the main component.

In the Main component I'm using getInitialProps to get the cookie token. But this is only working after refreshing the page. So right now I'm logging in and getting redirected. If I click on the button, there is no token. After refreshing the page, I do get a token.

How can I avoid this? I think I'm doing something wrong on server side...

Login

export class Login extends Component {
  render () {
    return (
      <Form id='login' onSubmit={this._onSubmit.bind(this)}>
        // Input fields
      </Form>
    )
  }

  _onSubmit = (event) => {
    event.preventDefault()
    const { username, password } = this.state

    // Sends mutation request to graphQL server
    this.props.signinUserMutation({
      variables: { username, password }
    }).then(response => {
      // Returns token
      const token = response.data.token
      if (token) {
        Cookies.set('auth-token', token)
        this.props.client.resetStore().then(() => {
          redirect({}, '/main')
        })
      }
    })
  }
}

Main

class Main extends Component {
  static async getInitialProps (context, apolloClient) {
    const { req } = context
    const initProps = {}

    if (req && req.headers) {
      const cookies = req.headers.cookie
      if (typeof cookies === 'string') {
        const cookiesJSON = jsHttpCookie.parse(cookies)
        initProps.token = cookiesJSON['auth-token']
      }
    }

    return initProps
  }

  clickIt = () => {
    console.log(this.props.token)
  }

  render () {
    return (<Button onClick={this.clickIt.bind(this)})
  }
}
like image 886
user3142695 Avatar asked Nov 19 '17 13:11

user3142695


1 Answers

After login your cookie is saved in browser, so you should use document.cookie in getInitialProps to get cookie value.

As I understand this code:

if (req && req.headers) {
  const cookies = req.headers.cookie
  if (typeof cookies === 'string') {
    const cookiesJSON = jsHttpCookie.parse(cookies)
    initProps.token = cookiesJSON['auth-token']
  }
}

is using request header to get cookie value, which will happen only after you make request to the server (when you refresh page). When navigation in browser happens that code doesn't run and you don’t get cookie. Thats why you need to get your cookie directly from browser document.cookie.

Consider using localStorage for saving auth tokens instead cookie, it has better api.

Since componentDidMount is executed only in the browser, use it to take cookie value and place it in redux store:

componentDidMount() {
    placeTokenInReduxStoreAction(Cookies.get('auth-token'));
}

I assume you use cookies-js

like image 110
zarcode Avatar answered Nov 01 '22 22:11

zarcode