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 个参数(令牌、卡号和密码)

就是说,当我再次输入用户凭据时 ,我收到 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;
}