Я боролся с проблемой аутентификации в течение нескольких часов.Я успешно вхожу в систему из интерфейса React, но не могу обновить заголовки токеном в контексте.После входа в систему мне нужно обновить страницу, чтобы успешно запросить зарегистрированного пользователя.Функция setContext запускается до того, как функция входа в систему обновляет токен в localStorage.
Я попытался также выполнить запрос с client.query({ query: LOGGED_USER })
в хуке useEffect
, но результат тот же.Мне всегда нужно обновить страницу до того, как LOGGED_USER
вернет что-то отличное от null
.
INDEX.JS
const httpLink = createHttpLink({
uri: 'http://localhost:4000/graphql'
})
const authLink = setContext((_, { headers }) => {
// After login this function is run. The problem is that at that point
// there is still token in the local storage and therefore the authorization
// header is null.
const token = localStorage.getItem('library-user-token')
return {
headers: {
...headers,
authorization: token ? `bearer ${token}` : null,
}
}
})
const client = new ApolloClient({
link: authLink.concat(httpLink),
cache: new InMemoryCache()
})
ReactDOM.render(
<ApolloProvider client={client}>
<App />
</ApolloProvider>,
document.getElementById('root'))
APP.JS
const LOGIN = gql`
mutation login($username: String!, $password: String!) {
login(
username: $username,
password: $password
) {
value
}
}
`
const LOGGED_USER = gql`
{
me {
username
favoriteGenre
}
}
`
const App = () => {
const [page, setPage] = useState('authors')
const [token, setToken] = useState(null)
const [loggedUser, setLoggedUser] = useState(null)
const loggedUserResult = useQuery(LOGGED_USER)
const authorResult = useQuery(ALL_AUTHORS)
const bookResult = useQuery(ALL_BOOKS)
const client = useApolloClient()
useEffect(() => {
setToken(localStorage.getItem('library-user-token'))
}, [])
const login = useMutation(LOGIN)
return (
<div>
<LoginForm
show={page === 'login'}
login={login}
setToken={(token) => setToken(token)}
setPage={setPage}
/>
</div>
)
}
LOGINFORM.JS
const LoginForm = (props) => {
if (!props.show) {
return null
}
const [username, setUsername] = useState('')
const [password, setPassword] = useState('')
const loginUser = async (event) => {
event.preventDefault()
try {
const result = await props.login({
variables: { username, password }
})
// Context updates here so the token is not yet is the localStorage and
// therefore LOGGED_USER query returns null
const token = result.data.login.value
props.setToken(token)
localStorage.setItem('library-user-token', token)
await props.login({
variables: { username, password }
})
props.setToken(token)
props.setPage('authors')
} catch(error){
console.log(error.message);
}
}
Каков будет правильный способ запроса зарегистрированного пользователя из базы данных без обновления страницы?