我已经为认证问题苦苦挣扎了好几个小时。我已从React前端成功登录,但无法在上下文中使用令牌更新标头。登录后,我需要刷新页面以成功查询登录的用户。在登录功能更新localStorage中的令牌之前,将运行setContext函数。
我也尝试过在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);
}
}
在不刷新页面的情况下从数据库查询登录用户的正确方法是什么?
答案 0 :(得分:0)
为了修改和设置请求标头中的令牌,您可以使用Apollo docs suggested这样的中间件:
使用HTTP时识别身份的另一种常用方法是发送授权标头。通过将Apollo链接链接在一起,可以轻松地向每个HTTP请求添加授权标头。在此示例中,每次发送请求时,我们将从localStorage中提取登录令牌:
x2
我在GraphQL应用程序中遵循相同的设置。