#javascript #reactjs #graphql #react-apollo #apollo-client
#javascript #reactjs #graphql #react-apollo #apollo-клиент
Вопрос:
Создание приложения, которое позволяет вам регистрироваться и входить в систему пользователя в базе данных. После регистрации / входа в систему приложение перемещает вас к контенту.
Код для процесса авторизации:
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 amp;amp;
<ErrorMessage className="mistake">
{error.message}
</ErrorMessage>
}
</div>
</div>
</>
)
}
export default Auth
Как вы можете видеть после завершения мутации, мне нужно повторно выполнить выборку моего запроса CURRENT_USER, чтобы понять, кто является текущим пользователем, и переместить пользователя к контенту. Я делаю это здесь:
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))
})
Код работает, но проблема в том, что я не хочу повторную выборку запроса таким образом: импортируйте сам запрос CURRENT_USER, получите функцию повторной выборки из useQuery hook и используйте ее внутри OnCompleted опции мутации.
ApolloClient предоставляет следующее:
- Я могу поместить
refetchQueries
опцию внутри крючка useMutation для повторной выборки моего запроса CURRENT_USER таким образом: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))
})
Этот подход не работает, потому что опция refetchQueries обновляет запрос CURRENT_USER до того, как я получу и помещу токен из результата мутации в localStorage. Таким образом, пользователь не перемещается в содержимое, потому что результат запроса CURRENT_USER пуст, а приложение показывает пользователю ошибку.
- Я могу использовать пакет npm ‘refetch-queries’. Он предоставляет возможность повторной выборки запросов Apollo в любом месте по имени и частичным переменным. Идеально подходит для моего случая и выглядит так:
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))
})
Итак, здесь я использую эту опцию внутри OnCompleted option и после помещения токена в localStorage. В моем случае кажется идеальным, но не работает. Я понятия не имею, почему, он выдает ту же ошибку, которая показывает, что результат запроса CURRENT_USER пуст. Возможно, пакет не поддерживается.
Я хочу повторно выполнить выборку запроса CURRENT_USER после перехода пользователя к контенту и до инициализации содержимого (компонента страниц). Но как это сделать, используя хук useEffect внутри содержимого (компонент Pages) и без метода componentWillMount.
И какова наилучшая практика повторной выборки запросов после мутации в моей ситуации?
Комментарии:
1. вы можете «поймать» и сохранить токен в ссылке… apollographql.com/docs/react/networking /…
2. @xadm, я уже использую это в заголовках типа: authorization: token ?
Bearer ${token}
: «»3. при получении, а не в этом направлении