Proper way of refetching queries after mutation in React + ApolloClient project

我与影子孤独终老i 提交于 2021-01-28 06:10:14

问题


Creating an app which allows you to sign up and sign in user in the database. After sign up / sign in process the app moves you to the content.

Code for authorization process:

const Auth = ({ handleSetAuthorized }) => {
  const { refetch } = useQuery(CURRENT_USER)
  const { error } = useSelector(({ error }) => error)
  const history = useHistory()
  const dispatch = useDispatch()

  const [signup] = useMutation(SIGN_UP, {
    onCompleted: async (data) => {
      const token = data.signup
      localStorage.setItem("token", token)
      await refetch()
      handleSetAuthorized()
      history.push("/pages/edituser")
    },
    onError: error => dispatch(getError(error))
  })

  const [login] = useMutation(SIGN_IN, {
    onCompleted: async (data) => {
      const token = data.login.token
      localStorage.setItem("token", token)
      await refetch()
      handleSetAuthorized()
      history.push("/pages/process")
    },
    onError: error => dispatch(getError(error))
  })

  const signUp = (values) => {
    signup({
      variables: {
        firstName: values.firstName,
        secondName: values.secondName,
        email: values.email,
        password: values.password,
      }
    })
  }

  const signIn = (values) =>{
    login({
      variables: {
        email: values.email,
        password: values.password,
      }
    })
  }

  const removeError = () => {
    dispatch(cleanError())
  }

  return (
    <>
      <div className="auth">
        <img 
          className="auth__logo"
          src={logo} 
          alt="logo"
        />
        <div className="auth__content">
          <Switch>
            <Route path="/auth/signin" >
              <SignIn onSubmit={signIn} removeError={removeError}/>
            </Route> 
            <Route path="/auth/signup">
              <SignUp onSubmit={signUp} removeError={removeError}/>
            </Route>   
          </Switch>
          {error &&
            <ErrorMessage className="mistake">
              {error.message}
            </ErrorMessage>
          }
        </div>
      </div>
    </>
  )
}

export default Auth

As you can see after mutation is completed, I need to refetch my CURRENT_USER query to understand who is current user and to move user to the content. I do that here:

  const { refetch } = useQuery(CURRENT_USER)

  const [signup] = useMutation(SIGN_UP, {
    onCompleted: async (data) => {
      const token = data.signup
      localStorage.setItem("token", token)
      await refetch()                        // <- HERE!
      handleSetAuthorized()
      history.push("/pages/edituser")
    },
    onError: error => dispatch(getError(error))
  })

Code works but the problem is I don't want to refetch query like that: import CURRENT_USER query itself, get refetch function from useQuery hook and use it inside onCompleted option of mutation.

ApolloClient provides next:

  1. I can put refetchQueries option inside useMutation hook to refetch my CURRENT_USER query like that:

    const [signup] = useMutation(SIGN_UP, {
     refetchQueries: [{query: CURRENT_USER }],   // <- HERE!
     onCompleted: (data) => {
       const token = data.signup
       localStorage.setItem("token", token)
       handleSetAuthorized()
       history.push("/pages/edituser")
     },
     onError: error => dispatch(getError(error))
    

    })

That approach doesn't work because refetchQueries option updates CURRENT_USER query before I get and put token from mutation result in localStorage. So user is not moved to content because CURRENT_USER query result is empty and app shows user a mistake.

  1. I can use 'refetch-queries' npm package. It provides the option to refetch Apollo queries anywhere by name and partial variables. Perfect for my case and look like that:

    const [signup] = useMutation(SIGN_UP, {
     onCompleted: (data) => {
       const token = data.signup
       localStorage.setItem("token", token)
       refetchQueries: [{query: CURRENT_USER }],   // <- HERE!
       handleSetAuthorized()
       history.push("/pages/edituser")
     },
     onError: error => dispatch(getError(error))
    

    })

So here I use that option inside onCompleted option and after putting token in localStorage. Seems perfect in my case but doesn't work. I have no idea why, it throws the same mistake which shows that CURRENT_USER query result is empty. Maybe package is not supported.

My wish is to refetch CURRENT_USER query after pushing user to the content and before content (Pages component) initialization. But how to do that using useEffect hook inside content (Pages component) and without componentWillMount method.

And what is the best practice for refetching queries after mutation in my situation?

来源:https://stackoverflow.com/questions/65038096/proper-way-of-refetching-queries-after-mutation-in-react-apolloclient-project

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!