当前位置: 首页 > 知识库问答 >
问题:

受保护的路由反应路由器4不使用存储在Redux中的身份验证状态

慕容铭
2023-03-14

根据这个例子,我试图在React路由器v4中创建一个经过身份验证的路由。为后代显示代码:

function PrivateRoute ({component: Component, authed, ...rest}) {
  return (
    <Route
      {...rest}
      render={(props) => (!!authed)
        ? <Component {...props} />
        : <Redirect to={{pathname: '/login', state: {from: props.location}}} />}
    />
  )
}

我的身份验证状态(Authed)在减速器中初始化为空对象,它来源于Redux存储。这就是我的pp.js的样子:

class App extends Component {
  componentDidMount() {
    const token = localStorage.getItem("token");
    if (token) {
      this.props.fetchUser();
    }
  }

  render() {
    return (
      <Router>
        <div>
          <PrivateRoute authed={this.props.authed} path='/dashboard' component={Dashboard} />
          />
        </div>
      </Router>
    );
  }
}

问题是Authed状态以未定义的方式开始,然后,一旦安装了路由器组件,它将状态更新为true。然而,这有点晚了,因为用户已经被重定向回登录页面。我还尝试用组件WillMount()替换组件didMount()生命周期方法,但这也没有解决问题。

你有什么建议?

更新1:我解决这个问题的唯一方法是在返回

  render() {
    if (!!this.props.authed) {
      return (
        <Router>
      <div>
      ...

更新2:我正在使用Redux Thunk中间件来调度操作。状态作为道具正确传递-我正在使用PrivateRoute组件中的console.log()方法验证状态是否正确变化。问题当然是它的变异较晚,而且路由已经在重定向用户。

减速机粘贴规范及作用...

行动:

export const fetchUser = () => async dispatch => {
  dispatch({ type: FETCHING_USER });
  try {
    const res = await axios.get(`${API_URL}/api/current_user`, {
      headers: { authorization: localStorage.getItem("token") }
    });
    dispatch({ type: FETCH_USER, payload: res.data });
  } catch (err) {
    // dispatch error action types
  }
};

减速器:

const initialState = {
  authed: {},
  isFetching: false
};
...
    case FETCH_USER: // user authenticated
      return { ...state, isFetching: false, authed: action.payload };

共有3个答案

魏松
2023-03-14

从理论上讲,您需要从节点API调用中获得一个promise,而您现在没有得到这个promise。您需要进行架构更改。我建议您使用redux promise中间件这是一个redux中间件。我的github帐户中有一个示例项目。如果您对this.props.fetchUser()的调用已完成或未完成,您将收到通知,基于您可以处理此异步问题的promise。如果需要帮助的话,去那家回购银行问我。

左华灿
2023-03-14

同样的问题也发生在我身上,我正在使用一个临时黑客来解决它,方法是在localstore中存储一个加密值,然后在我的私人路线组件中解密它,并检查值是否匹配。

action.js

localStorage.setItem('isAuthenticated', encryptedText);

privaterout.js

if (localStorage.getItem('isAuthenticated')) {
const isAuth = decryptedText === my_value;
return (
     <Route
        {...rest}
        render={(props) =>
           isAuth ? <Component {...props} /> : <Redirect to="/login" />
        }
     />
  );
} else {
      return <Redirect to="/login" />;
   }

由于localStorage速度更快,因此它不会进行不必要的重定向。如果有人删除localStorage,他们将被重定向到/login注意:这是一个临时解决方案。

韩祯
2023-03-14

我也有同样的问题,据我所知,你的更新应该是答案。然而,经过进一步调查,我认为这是一个架构问题。私有路由的当前实现取决于同步的信息。

如果我们实际地考虑一下,ProtectedRoute基本上会根据应用程序的状态返回重定向或组件。我们可以将所有路由包装在一个组件中,并从存储中提取信息,而不是将每个路由包装在一个组件中。

是的,每个受保护的路由需要编写更多的代码,您需要测试这是否是一个可行的解决方案。

编辑:忘记提到另一个很大的原因,这是一个架构问题,如果用户刷新一个受保护的页面,他们将被重定向。

更新更好的解决方案:在刷新时,如果他们经过身份验证,它将重定向到他们的目标urihttps://tylermcginnis.com/react-router-protected-routes-authentication/

解决方案1

//You can make this a method instead, that way we don't need to pass authed as an argument
function Protected(authed, Component, props) {
  return !!authed
    ? <Component {...props} />
    : <Redirect to='/login' />
}

class AppRouter extends React.PureComponent {
  componentDidMount() {
    const token = localStorage.getItem("token");
    if (token) {
      this.props.fetchUser();
    }
  }

  render() {
    let authed = this.props.authed

    return (
      <Router>
          <Route path='/protected' render={(props) => Protected(authed, Component, props)} />
      </Router>
    )
  }
}

class App extends Component {
  render() {
    return (
      <Provider store={store}>
        <AppRouter />
      </Provider>
    )
  }
}

解决方案2或者我们可以只检查每个组件(是的,这很痛苦)

class Component extends React.Component {
  render() {
    return (
      !!this.props.authed
        ? <div>...</div>
        : <Redirect to='/' />
    )
  }
}
 类似资料:
  • 根据React Router给出的示例,我正在尝试创建一个受保护的路由,当用户未被授权使用Find Router for Relay Modern时,该路由将重定向到: 我用真实的登录逻辑替换了fakeAuth,但其余的都是一样的。这条路线就是不渲染。 发现路由器似乎是轻的例子围绕这个特定的问题。有什么想法吗?

  • 我一直在搜索net,试图找到任何定义如何在流星和响应路由器4中处理身份验证的地方。 基本上,我希望某些路由只对经过身份验证的用户可用。有相关文件吗? 阿西尔

  • 我试图实现身份验证的路由,但发现React路由器4现在阻止此工作: 错误是: 警告:您不应使用

  • 我正在react路由器v4上实现受保护的路由。我试图将“isAuthenticated”值从“Login”组件传递到“Authenticated”组件,但得到“false”值。 也许我用错了方法,任何人都可以帮助解决这个问题吗? 我的代码如下: 登录。js提供“isAuthenticated”控件 Authenticated.js需要获得“isAuthenticated”值(true)来呈现受保护

  • 我正在使用react路由器v4和redux,如果用户未登录,我想使用私有和受保护的路由重定向。 我有一个路由组件: 它是这样实现的: 这是私人路线: 传递prop的最佳方式是什么,如果我连接Routes组件并从那里传递是否可以,或者应该从其他地方传递,或者连接需要它的每个组件并从那里读取?此外,这种方法如何处理嵌套路由,如?谢谢

  • 在< code>/users下,我有一些需要身份验证令牌的路由,还有一些不需要。为了实现这一点,我做了以下工作。 然后我按照以下方式安装这些路线。 当我向< code>/users发送POST时,它运行预期的路径,但是当< code>next()被调用时,< code > protected _ middleware 运行。这是因为它在标有“D”的行中找到了下一个< code>/users定义。