【问题标题】:React Relay Modern redirecting to another page when receiving 401 error on network environment在网络环境中收到 401 错误时 React Relay Modern 重定向到另一个页面
【发布时间】:2018-04-23 22:22:59
【问题描述】:

我在我的 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 错误,我只想重定向到登录页面,但我找不到合适的方法。

【问题讨论】:

  • 你弄清楚如何处理这个问题了吗?
  • 这有什么更新吗?

标签: reactjs react-router relayjs relaymodern


【解决方案1】:

我没有使用中继,而是使用渲染道具。我遇到了同样的问题。我能够使用 window 对象解决它。

 if (response.statusText === "Unauthorized") {
     window.location = `${window.location.protocol}//${window.location.host}/login`;
 } else {
   return response.json();
 }

【讨论】:

    【解决方案2】:

    您可以使用 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 组件。

    顺便说一句:这样您还可以避免使用会降低性能的localStorage

    【讨论】:

      猜你喜欢
      • 2017-11-01
      • 2021-06-24
      • 1970-01-01
      • 2018-08-30
      • 1970-01-01
      • 2021-12-25
      • 1970-01-01
      • 2015-12-07
      • 1970-01-01
      相关资源
      最近更新 更多