MOBX 正在连接一个可观察对象而不是更新它
MOBX is concatenating an observable instead of updating it
我正在使用 Mobx、MUI V5、react-router V6 和 react-hook-form 构建登录页面。
我的第一个 API 调用是对应用程序进行身份验证,apiAuth()
将 return 需要传递给所有后续 API 调用的令牌。
在下一次调用 userAuth()
时,我尝试验证用户凭据。
如您所见,该方法采用 3 个参数(令牌、卡号和密码)
- 当用户凭据有效时,我可以成功登录。
- 当用户凭据在第一次尝试 时无效时,它会作为
预期的。我从 API 收到 400(错误请求)错误并在
界面。
就是说,当我再次输入用户凭据时 ,我收到 401(未授权)错误。
进一步检查请求 headers 后,当我比较两次 userAuth()
调用中的授权 header 时,我发现第二次调用中的令牌值与前一个令牌
关于此行为的原因有什么想法吗?
我的 AuthStore
看起来如下:
class AuthStore {
isAuth = false
isAuthFail = false
AuthFailObj = {}
bearerToken = ''
cardNum = ''
password=''
constructor() {
makeObservable(this, {
isAuth: observable,
AuthFailObj: observable,
isAuthFail:observable,
bearerToken: observable,
cardNum: observable,
password: observable,
auth: action,
setIsAuth: action,
setToken: action,
setCardNum: action,
setPassword: action,
setIsAuthFail: action,
setAuthFailObj: action
})
}
setIsAuth = isAuth => {
this.isAuth = isAuth
}
setToken = bearerToken => {
this.bearerToken = bearerToken
}
setCardNum = cardNum => {
this.cardNum = cardNum
}
setPassword = password => {
this.password = password
}
setIsAuthFail = b => {
this.isAuthFail = b
}
setAuthFailObj = ojb => {
this.AuthFailObj = ojb
}
auth = async () => {
const apiRes = await apiAuth()
if (apiRes.status === 200){
const apiData = await apiRes.text()
this.setToken(JSON.parse(apiData)[0].token)
}
const userAuthRes = await userAuth(this.bearerToken, this.password, this.cardNum)
if (!userAuthRes.ok){
this.setIsAuthFail(true)
const errRes = await userAuthRes.text()
userAuthRes.status === 400 && this.setAuthFailObj(JSON.parse(errRes))
userAuthRes.status === 401 && this.setAuthFailObj('401 (Unauthorized)')
}
if (userAuthRes.ok){
const userAuthData = await userAuthRes.text()
userStore.updateUserProfile(JSON.parse(userAuthData))
this.setIsAuth(true)
}
}
}
export default new AuthStore()
在登录表单中,提交方法如下所示:
const submit = async (data) => {
AuthStore.setCardNum(data.Card_Number)
AuthStore.setPassword(data.Password)
setToggle(true)
await AuthStore.auth()
if (AuthStore.isAuth) {
navigate('/dashboard')
} else {
// clear form
}
}
最后,PrivateRoute
逻辑读取很简单:
const PrivateRoute = () => {
return AuthStore.isAuth ? <Outlet /> : <Navigate to='/' />
}
函数userAuth()
const myHeaders = new window.Headers()
const { REACT_APP_API_ACC_MNG_AUTH_URL } = process.env
const userAuth = async (bearerToken, password, cardNum) => {
myHeaders.append('Authorization', `Bearer ${bearerToken}`)
myHeaders.append('Content-Type', 'application/json')
const raw = JSON.stringify({
cardNumber: cardNum,
pinNumber: password
})
const requestOptions = {
method: 'POST',
headers: myHeaders,
body: raw,
redirect: 'follow'
}
const response = await window.fetch(REACT_APP_API_ACC_MNG_AUTH_URL, requestOptions)
return response
}
问题是您正在使用 Headers API 并附加到 header 而不是 setting them, which exist outside the function scope and are updated. From MDN:
The append() method of the Headers interface appends a new value onto an existing header inside a Headers object, or adds the header if it does not already exist.
所以每次您发出请求时,如果您追加 header,它将被添加到现有值上。您可以将 headers 声明移到函数内部,并在每次发出请求时创建一个新的 object:
const { REACT_APP_API_ACC_MNG_AUTH_URL } = process.env
const userAuth = async (bearerToken, password, cardNum) => {
const myHeaders = new window.Headers()
myHeaders.append('Authorization', `Bearer ${bearerToken}`)
myHeaders.append('Content-Type', 'application/json')
const raw = JSON.stringify({
cardNumber: cardNum,
pinNumber: password
})
const requestOptions = {
method: 'POST',
headers: myHeaders,
body: raw,
redirect: 'follow'
}
const response = await window.fetch(REACT_APP_API_ACC_MNG_AUTH_URL, requestOptions)
return response
}
或者您可以将它们作为 object 传入,这是 Fetch API:
允许的
const userAuth = async (bearerToken, password, cardNum) => {
const raw = JSON.stringify({
cardNumber: cardNum,
pinNumber: password
});
const requestOptions = {
method: 'POST',
headers: myHeaders,
body: raw,
redirect: 'follow',
headers: {
'Authorization': `Bearer ${bearerToken}`,
'Content-Type': 'application/json',
}
};
const response = await window.fetch(REACT_APP_API_ACC_MNG_AUTH_URL, requestOptions);
return response;
}
我正在使用 Mobx、MUI V5、react-router V6 和 react-hook-form 构建登录页面。
我的第一个 API 调用是对应用程序进行身份验证,apiAuth()
将 return 需要传递给所有后续 API 调用的令牌。
在下一次调用 userAuth()
时,我尝试验证用户凭据。
如您所见,该方法采用 3 个参数(令牌、卡号和密码)
- 当用户凭据有效时,我可以成功登录。
- 当用户凭据在第一次尝试 时无效时,它会作为 预期的。我从 API 收到 400(错误请求)错误并在 界面。
就是说,当我再次输入用户凭据时 ,我收到 401(未授权)错误。
进一步检查请求 headers 后,当我比较两次 userAuth()
调用中的授权 header 时,我发现第二次调用中的令牌值与前一个令牌
关于此行为的原因有什么想法吗?
我的 AuthStore
看起来如下:
class AuthStore {
isAuth = false
isAuthFail = false
AuthFailObj = {}
bearerToken = ''
cardNum = ''
password=''
constructor() {
makeObservable(this, {
isAuth: observable,
AuthFailObj: observable,
isAuthFail:observable,
bearerToken: observable,
cardNum: observable,
password: observable,
auth: action,
setIsAuth: action,
setToken: action,
setCardNum: action,
setPassword: action,
setIsAuthFail: action,
setAuthFailObj: action
})
}
setIsAuth = isAuth => {
this.isAuth = isAuth
}
setToken = bearerToken => {
this.bearerToken = bearerToken
}
setCardNum = cardNum => {
this.cardNum = cardNum
}
setPassword = password => {
this.password = password
}
setIsAuthFail = b => {
this.isAuthFail = b
}
setAuthFailObj = ojb => {
this.AuthFailObj = ojb
}
auth = async () => {
const apiRes = await apiAuth()
if (apiRes.status === 200){
const apiData = await apiRes.text()
this.setToken(JSON.parse(apiData)[0].token)
}
const userAuthRes = await userAuth(this.bearerToken, this.password, this.cardNum)
if (!userAuthRes.ok){
this.setIsAuthFail(true)
const errRes = await userAuthRes.text()
userAuthRes.status === 400 && this.setAuthFailObj(JSON.parse(errRes))
userAuthRes.status === 401 && this.setAuthFailObj('401 (Unauthorized)')
}
if (userAuthRes.ok){
const userAuthData = await userAuthRes.text()
userStore.updateUserProfile(JSON.parse(userAuthData))
this.setIsAuth(true)
}
}
}
export default new AuthStore()
在登录表单中,提交方法如下所示:
const submit = async (data) => {
AuthStore.setCardNum(data.Card_Number)
AuthStore.setPassword(data.Password)
setToggle(true)
await AuthStore.auth()
if (AuthStore.isAuth) {
navigate('/dashboard')
} else {
// clear form
}
}
最后,PrivateRoute
逻辑读取很简单:
const PrivateRoute = () => {
return AuthStore.isAuth ? <Outlet /> : <Navigate to='/' />
}
函数userAuth()
const myHeaders = new window.Headers()
const { REACT_APP_API_ACC_MNG_AUTH_URL } = process.env
const userAuth = async (bearerToken, password, cardNum) => {
myHeaders.append('Authorization', `Bearer ${bearerToken}`)
myHeaders.append('Content-Type', 'application/json')
const raw = JSON.stringify({
cardNumber: cardNum,
pinNumber: password
})
const requestOptions = {
method: 'POST',
headers: myHeaders,
body: raw,
redirect: 'follow'
}
const response = await window.fetch(REACT_APP_API_ACC_MNG_AUTH_URL, requestOptions)
return response
}
问题是您正在使用 Headers API 并附加到 header 而不是 setting them, which exist outside the function scope and are updated. From MDN:
The append() method of the Headers interface appends a new value onto an existing header inside a Headers object, or adds the header if it does not already exist.
所以每次您发出请求时,如果您追加 header,它将被添加到现有值上。您可以将 headers 声明移到函数内部,并在每次发出请求时创建一个新的 object:
const { REACT_APP_API_ACC_MNG_AUTH_URL } = process.env
const userAuth = async (bearerToken, password, cardNum) => {
const myHeaders = new window.Headers()
myHeaders.append('Authorization', `Bearer ${bearerToken}`)
myHeaders.append('Content-Type', 'application/json')
const raw = JSON.stringify({
cardNumber: cardNum,
pinNumber: password
})
const requestOptions = {
method: 'POST',
headers: myHeaders,
body: raw,
redirect: 'follow'
}
const response = await window.fetch(REACT_APP_API_ACC_MNG_AUTH_URL, requestOptions)
return response
}
或者您可以将它们作为 object 传入,这是 Fetch API:
允许的const userAuth = async (bearerToken, password, cardNum) => {
const raw = JSON.stringify({
cardNumber: cardNum,
pinNumber: password
});
const requestOptions = {
method: 'POST',
headers: myHeaders,
body: raw,
redirect: 'follow',
headers: {
'Authorization': `Bearer ${bearerToken}`,
'Content-Type': 'application/json',
}
};
const response = await window.fetch(REACT_APP_API_ACC_MNG_AUTH_URL, requestOptions);
return response;
}