登录系统中Axios请求仅在第二次提交时生效的问题排查与解决方案咨询
Let's break down why you're hitting this error on the first login click, and fix it cleanly without relying on timers.
The Root Cause
Your issue stems from two key missteps:
- React state updates are asynchronous: When you call
setUser(result)in your login request's.thenhandler, React doesn't update theuserstate right away. So when you callfetchData()immediately after, theuservariable is still its initialundefinedvalue—hence the error when trying to accessuser.data. - Incorrect callback syntax: You're invoking
fetchData()immediately instead of passing it as a callback to.then. Even if you fixed the syntax, the async state update would still leaveuserundefined whenfetchDataruns the first time.
Solution 1: Use the API Response Directly (Recommended)
Instead of waiting for React's state to update, pass the user ID directly from the login response to fetchData. This skips the asynchronous state delay entirely.
Modified Frontend Code
First, update fetchData to accept a userId parameter:
async function fetchData(userId) { const sentItem = { user: userId } await axios.post('http://localhost:3001/api', sentItem) .then(result => setGetBasic(result)) }
Then adjust your loginFunc to use the response data immediately:
const loginFunc = async () => { const checkUser = { email: Item.email, password: Item.password } await axios.post('http://localhost:3001/api/login', checkUser) .then(result => { setUser(result); // Pass the user ID directly from the response, not state fetchData(result.data.user._id); }) }
Also, add the missing handleChange function (referenced in your JSX but not defined):
const handleChange = (e) => { setItem(prev => ({ ...prev, [e.target.name]: e.target.value })); };
Solution 2: Use useEffect to Trigger fetchData When State Updates
If you prefer to rely on React state, use a useEffect hook that runs whenever the user state changes. This ensures fetchData only runs after user has been successfully updated.
Modified Frontend Code
Add the useEffect hook at the top of your component:
import { useState, useEffect } from 'react'; // Ensure useEffect is imported function Login() { const [user, setUser] = useState() const [getBasic, setGetBasic] = useState() const [Item, setItem] = useState({ email: '', password: '' }); // Trigger fetchData whenever user state updates useEffect(() => { if (user) { fetchData(); } }, [user]); // Dependency array: only run when user changes async function fetchData() { const sentItem = { user: user.data.user._id, } await axios.post('http://localhost:3001/api', sentItem) .then(result => setGetBasic(result)) } const loginFunc = async () => { const checkUser = { email: Item.email, password: Item.password } await axios.post('http://localhost:3001/api/login', checkUser) .then(result => setUser(result)) // Remove the direct fetchData() call here } // Add the missing handleChange function const handleChange = (e) => { setItem(prev => ({ ...prev, [e.target.name]: e.target.value })); }; // Rest of your component code remains the same... }
Bonus: Fix Backend Response Gap
Your /api/login endpoint doesn't send a response when credentials are invalid, leaving the frontend hanging indefinitely. Add an error response for failed logins:
app.post('/api/login', async (req, res) => { const user1 = await User.findOne({ email: req.body.email, password: req.body.password }) if (user1) { const payload = { name: req.body.name, email: req.body.email }; const token = jwt.sign(payload, private_key, { expiresIn: '200s' }); console.log('correct login') res.status(200).send({ auth: true, token: token, user: user1 }) // Fixed: send actual token instead of `true` } else { console.log('incorrect login') // Add this to send an error response res.status(401).send({ auth: false, message: 'Invalid email or password' }) } })
内容的提问来源于stack exchange,提问作者Caleb

