简体   繁体   中英

How can I store user information in Next.JS + Rails API backend?

I'm new to Next.js and React in general, I used to develop the whole application with Rails.

I want to combine rails API with Next.js. My JWT backend has an endpoint that returns a JSON object containing user information when requested with JWT token in header. In my _app.js , I'm trying to authenticate users using this backend by using useState and useEffect like this:

export default function MyApp(props) {
  const [user, setUser] = useState({})

  useEffect(function () {
    const token = localStorage.getItem('token')
    if (token) {
      fetch('http://localhost:3001/auto_login', {
        headers: {
          Authorization: `Bearer ${token}`,
        },
      })
        .then((resp) => resp.json())
        .then((data) => {
          console.log(data) // {id: 1, email: "test@example.com"}
          setUser(data)
          console.log(user) // {}
        })
    }
  }, [])

  return (
    <>
      { // some code }
    </>
  )
}

In my first console.log , it returns an object that I would like to store in user . However, in my second console.log where I expect to return the same result, I get an empty object instead.

Am I missing anything, or are there any points that I have to take into consideration as a whole? I've already tried implementing this with async/await , but that didn't seem to solve my problem.

It's because that effect isn't aware of the dependent objects state change.

If you did this (see code below) you'd see user being logged. Eg within the context of the 1st effect's 1st run, even though you're setting the user state, inside the effect it's not aware of the new value.

The sequence is like this.

  1. Component loads
  2. Effect runs with initial state of [] (this effectively means run once, and uses the current state, user => {} )
  3. state [] => console.log(data)
  4. state [] => setUser(data)
  5. state [] => console.log(user) // currently {}
  6. effect is done.

Look at the useEffect explanation here

export default function MyApp(props) {
 const [user, setUser] = useState({ email: null, id: null })

 // same useEffect / modify your existing code 
 // you could add user in here .but then the api call will fire again, 
 // thus an infinite loop could happen, so you would need to wrap 
 // the call in an if to check to prevent that, see my alterations
 useEffect(function () {
    const token = localStorage.getItem('token')
    if (token && !user.id) {
      fetch('http://localhost:3001/auto_login', {
        headers: {
          Authorization: `Bearer ${token}`,
        },
      })
        .then((resp) => resp.json())
        .then((data) => {
          console.log(data) // {id: 1, email: "test@example.com"}
          setUser(data)
          console.log(user);
        })
    }
  }, [user]); // [] => changed to => [user]


 // new / additional useEffect 
 // alternatively this effect will trigger when 
 // this objects state changes (and you wont need the checks as per above)
  useEffect(() => {
    console.log(user);
  }, [user]);  

  return (
    <>
      { // some code, e.g if you referenced user here, example. user.email, it would work. }
      { // Would probably initially be empty, when when the ajax call completes the value would/could be set }
    </>
  )
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM