我在ReactJS RelayJS网络环境中使用JWT身份验证。服务器和客户端中的所有令牌检索和处理都很好。我正在使用react router v4进行路由。
我的问题是当我从服务器收到Unauthorized
消息时(状态码401)。如果用户在令牌过期后指向应用程序页面,即会发生这种情况。我需要做的是重定向到登录页面。这是我希望的代码:
import { Environment, Network, RecordSource, Store } from 'relay-runtime';
const SERVER = 'http://localhost:3000/graphql';
const source = new RecordSource();
const store = new Store(source);
function fetchQuery(operation, variables, cacheConfig, uploadables) {
const token = localStorage.getItem('jwtToken');
return fetch(SERVER, {
method: 'POST',
headers: {
Authorization: 'Bearer ' + token,
Accept: 'application/json',
'Content-type': 'application/json'
},
body: JSON.stringify({
query: operation.text, // GraphQL text from input
variables
})
})
.then(response => {
// If not authorized, then move to default route
if (response.status === 401)
this.props.history.push('/login') <<=== THIS IS NOT POSSIBLE AS THERE IS NO this.history.push CONTEXT AT THIS POINT
else return response.json();
})
.catch(error => {
throw new Error(
'(environment): Error while fetching server data. Error: ' + error
);
});
}
const network = Network.create(fetchQuery);
const handlerProvider = null;
const environment = new Environment({
handlerProvider, // Can omit.
network,
store
});
export default environment;
自然地调用this.props.history.push
是不可能的,因为网络环境不是ReactJS组件,因此没有关联的属性。
我试图在这一点上抛出错误,例如:
if (response.status === 401)
throw new Error('Unauthorized');
但我在浏览器控制台上看到了错误,但在代码中无法正确处理。
我想做的就是在收到401错误的情况下重定向到登录页面,但我找不到合适的方法。
答案 0 :(得分:0)
我不使用中继而是渲染道具。我遇到了同样的问题。我能够使用window对象解决它。
if (response.statusText === "Unauthorized") {
window.location = `${window.location.protocol}//${window.location.host}/login`;
} else {
return response.json();
}
答案 1 :(得分:0)
您可以使用 useEnvironment
自定义挂钩。
export const useEnvironment = () => {
const history = useHistory(); // <--- Any hook using context works here
const fetchQuery = (operation, variables) => {
return fetch(".../graphql", {...})
.then(response => {
//...
// history.push('/login');
//...
})
.catch(...);
};
return new Environment({
network: Network.create(fetchQuery),
store: new Store(new RecordSource())
});
};
// ... later in the code
const environment = useEnvironment();
或者如果您使用类组件,则可以创建HOC或render-prop组件。
btw:这种方式还可以避免使用localStorage
,这会降低性能。