Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
69 views
in Technique[技术] by (71.8m points)

javascript - Using hook value in promise chain

I am trying to figure out how I can use the state value from a hook in a function. At the moment, I am able to use the value when the component is returned, but within my function it is appearing as undefined. Is there a limit to the scope of where state values can be accessed? I am trying to use this value as a workaround to the limitation in passing values down promise chains so I can check if a redirect should be triggered

Undefined line:

console.log(message) // undefined

Function where message is accessed:

const signIn = (e) => {
        
        e.preventDefault();
        console.log('Axios: signIn Triggered')
        axios.post('/api/auth/signin/', { email, password }, {
            headers: {
                'Content-Type': 'application/json'
            },
            withCredentials: true
        }).then((res) => {
            console.log('Success - res')
            console.log(res)
            const data = res.data;
            console.log(data.message)
            console.log(data.user)
            console.log(message)
            // Set user session state with returned user data
            setUser(data.user)
            setMessage(data.message)
        }).then(()=> {
            // On successful sigin, redirect to /app/profile/

            console.log(message) // returns `undefined`
            
            // if (message.status !== 'error'){
                // router.push('/app/profile/')
            // }
        }).catch((err) => {
            console.log(err)
            console.log(err.request)
            console.log(err.message)
        })
    }

Full Code:

import axios from 'axios';
import React, { useContext, useEffect, useState } from 'react'
import { useRouter } from 'next/router'
import { SessionContext }  from '../../../contexts/AppSession'

const SignInForm = () => {
    const [{ email, password }, setForm] = useState({ email: null, password: null })
    const [message, setMessage] = useState()
    const { user, setUser } = useContext(SessionContext) // here you are calling a hook at component body
    const router = useRouter()

    const handleChange = ({ target }) => {
        setForm( prevForm => ({
        ...prevForm,
        [target.name]: target.value
        }));
    }

    const signIn = (e) => {
        
        e.preventDefault();
        console.log('Axios: signIn Triggered')
        axios.post('/api/auth/signin/', { email, password }, {
            headers: {
                'Content-Type': 'application/json'
            },
            withCredentials: true
        }).then((res) => {
            console.log('Success - res')
            console.log(res)
            const data = res.data;
            console.log(data.message)
            console.log(data.user)
            console.log(message)
            // Set user session state with returned user data
            setUser(data.user)
            setMessage(data.message)
        }).then(()=> {
            // On successful sigin, redirect to /app/profile/
            console.log(message)
            
            // if (message.status !== 'error'){
                // router.push('/app/profile/')
            // }
        }).catch((err) => {
            console.log(err)
            console.log(err.request)
            console.log(err.message)
        })
    }

    useEffect(() => {
        console.log(user)
    }, [user]) // with that console.log will run on every user change

    return (
        <div className="signup-form">
            <div className="grid min-h-screen place-items-center">
                <div className="w-11/12 p-12 bg-white sm:w-8/12 md:w-1/2 lg:w-5/12">
                    <h1 className="text-xl font-semibold">Hello there ??, <span className="font-normal">please fill in your information to continue</span></h1>
                    <form className="mt-6" action="/api/auth/signin/" method="post">
                        <label htmlFor="email" className="block mt-2 text-xs font-semibold text-gray-600 uppercase">E-mail</label>
                        <input id="email" type="email" name="email" placeholder="[email protected]" autoComplete="email" className="block w-full p-3 mt-2 text-gray-700 bg-gray-200 appearance-none focus:outline-none focus:bg-gray-300 focus:shadow-inner" value={ email || '' } onChange={ handleChange } required />
                        <label htmlFor="password" className="block mt-2 text-xs font-semibold text-gray-600 uppercase">Password</label>
                        <input id="password" type="password" name="password" placeholder="********" autoComplete="new-password" className="block w-full p-3 mt-2 text-gray-700 bg-gray-200 appearance-none focus:outline-none focus:bg-gray-300 focus:shadow-inner" value={ password || '' } onChange={ handleChange } required />
                        <button type="submit" className="w-full py-3 mt-6 font-medium tracking-widest text-white uppercase bg-black shadow-lg focus:outline-none hover:bg-gray-900 hover:shadow-none" onClick={ signIn }>
                            Sign In
                        </button>
                        {message ?
                        <div className="bg-red-200 px-6 py-4 my-4 rounded-md text-lg flex items-center w-full">
                            <svg viewBox="0 0 24 24" className="text-red-600 w-10 h-10 sm:w-5 sm:h-5 mr-3">
                                <path fill="currentColor" d="M11.983,0a12.206,12.206,0,0,0-8.51,3.653A11.8,11.8,0,0,0,0,12.207,11.779,11.779,0,0,0,11.8,24h.214A12.111,12.111,0,0,0,24,11.791h0A11.766,11.766,0,0,0,11.983,0ZM10.5,16.542a1.476,1.476,0,0,1,1.449-1.53h.027a1.527,1.527,0,0,1,1.523,1.47,1.475,1.475,0,0,1-1.449,1.53h-.027A1.529,1.529,0,0,1,10.5,16.542ZM11,12.5v-6a1,1,0,0,1,2,0v6a1,1,0,1,1-2,0Z"></path>
                            </svg>
                            <span class="text-red-800">{ message.body }</span>
                        </div>
                            : null
                        }
                    </form>
                </div>
            </div>
        </div>
    )
}

export default SignInForm;
question from:https://stackoverflow.com/questions/65540991/using-hook-value-in-promise-chain

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Do not forget that arrow function always remember values in a moment the function was created... So in the beginning your message value is undefined and it will remain undefined till the moment the component will be rerender, so when you call setMessage it doesn't influence message value at all, it just gives a command to react that you'd like to change the state...

so if you want to see new value in next then block after setMessage(data.message) just return data.message and read it as a parameter in your next block

  setMessage(data.message)
  return data.message
}).then(newMessage => {
  // On successful sigin, redirect to /app/profile/
  console.log(newMessage)

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...