如何在API调用完成返回结果后正确更新React State
问题原因
你拿不到接口返回值核心是三个问题,和useEffect、回调逻辑无关:
- 前端
signup函数没有返回axios发起请求的Promise实例:函数内没有写return语句,默认返回undefined,.then里的return只是回调函数的内部返回值,不会被外层signup函数抛出,所以await signup(...)会直接拿到undefined,不会等接口请求完成。 - 后端FastAPI接口返回格式不规范:你用大括号包裹格式化后的字符串,实际返回的是Python单元素集合(set),序列化后会变成数组,前端需要取
[0]才能拿到文案,而且你把哈希后的密码拼在返回文案里存在安全风险。 - 表单提交逻辑缺
e.preventDefault(),默认提交行为会触发页面跳转,也会导致状态更新异常。
修改代码
1. 修正前端signup请求函数
给axios请求加上return,保证Promise链能被await捕获,两种写法都可以:
// 写法1:保留原有then链式调用,补全return function signup(name, email, password){ return axios.post('/register', { username: name, email: email, password: password }) .then(function (response) { return response.data; }) } // 写法2:改成async/await,逻辑更直观,不容易漏return async function signup(name, email, password) { const res = await axios.post('/register', { username: name, email: email, password: password }) return res.data }
2. 修正React组件提交逻辑
补全表单默认行为阻止、错误处理,拼接要求的文案前缀:
export default function Signup() { const [message, setMessage] = useState('Welcome') async function handleSubmit(e){ // 阻止表单默认提交跳转 e.preventDefault() try { const resText = await signup( usernameRef.current.value, emailRef.current.value, passwordRef.current.value ) // 拼接要求的hello前缀 setMessage(`hello ${resText}`) } catch (err) { setMessage('注册提交失败,请稍后重试') } } return( <div> <p>{message}</p> {/* 原有表单代码,提交事件绑定handleSubmit即可 */} </div> ) }
注:状态设置函数建议用小驼峰
setMessage,符合React社区约定,大写开头的Setmessage虽然能运行,但可读性差。
3. 修正FastAPI后端返回逻辑
去掉包裹返回值的大括号,直接返回字符串,同时删掉文案里拼接的密码字段:
@app.post("/register") async def user_register(user: UserIn_Pydantic): user_info = user.dict(exclude_unset=True) user_info["password"] = get_password_hash(user_info["password"]) user_obj = await User.create(**user_info) new_user = await user_pydantic.from_tortoise_orm(user_obj) await simple_send(email=[new_user.email], instance=new_user) # 直接返回字符串,去掉外层大括号,移除密码字段 return f"{new_user.username}, please check your email for verification"
改完之后提交表单就会等接口返回完整文案后,再更新页面显示的message内容,不会再出现undefined的问题。
内容的提问来源于stack exchange,提问作者KingJac
相关产品推荐
相关产品推荐

