【问题标题】:How to prevent component displaying before redirecting?如何在重定向之前防止组件显示?
【发布时间】:2020-01-06 22:00:54
【问题描述】:

我的 react/redux 应用程序出现问题。 我已经成功实现了登录功能——登录后重定向到主页。

我遇到的问题是,如果我转到 URL,然后输入 /login。登录屏幕显示一秒钟,然后重定向到主页。如何让它立即重定向?

注意:我能够使其工作的唯一方法不是检查状态 isAuthenticated,而是检查 localStorage 的令牌,然后重定向。

const App = () => {
  useEffect(() => {
    if (localStorage.token) {
      store.dispatch(loadUser());
    }
  });

  return (
    <Provider store={store}>
      <Router>
        <div id='js-scroll'>
          <Switch>
            <Route exact path='/' component={Home} />
            <Route exact path='/register' component={Register} />
            <Route exact path='/login' component={Login} />
          </Switch>
        </div>
      </Router>
    </Provider>
  );
};
const Login = ({ login, isAuthenticated }) => {
  if (isAuthenticated) {
    return <Redirect to='/' />;
  }

  return ( ... )

const mapStateToProps = state => ({
  isAuthenticated: state.authReducer.isAuthenticated
});

export default connect(
  mapStateToProps,
  { login }
)(Login);

【问题讨论】:

  • 您是否检查了 isAuthenticated 的值以及它如何随时间变化。这似乎只是它最初的值为 false,然后启动了一些进程来授权和调度该值的更改。
  • @MonVillalon 是正确的。

标签: reactjs redux react-redux


【解决方案1】:

渲染完成后调用 useEffect 钩子。在第一次渲染时将 isAuthenticated 设置为 false ,然后将其提交给 dom ,然后通过您的操作进行更改。

loadUser 函数可能是一个 thunk,使得这种中间状态更加明显,因为在让用户离开服务器时存在延迟。

如果是这种情况,解决方案是将 isAuthenticated 值从布尔标志转换为具有三个可能值的值。
例如:认证、认证、未认证

然后你会改变你的路线看起来像这样:

const Login = ({ login, authenticationStatus }) => {

  if(authenticationStatus === 'authenticating') {
    return null; // Or loading page
  } 

  if(authenticationStatus === 'authenticated') {
    return <Redirect to='/' />
  } 

  return ( ... )

【讨论】:

  • javascript if (isAuthenticated === null) { return null; } if (isAuthenticated === true) { return &lt;Redirect to='/' /&gt;; } if (isAuthenticated === false) { return (...) 这可行,但我不喜欢多个 if 语句,我更喜欢 isAuthenticated 由 loadUser 先解决,然后再渲染。
  • 使用多个 if 语句与一般方法无关。遗憾的是,您想要同步解决效果在一般意义上是不可能的。您将不得不等待请求。返回 null 并不理想,因为你不会渲染任何东西,这就是我建议使用加载组件状态的原因,这个加载组件可以是任何东西,甚至可以是带有模拟数据或骨架的 Home 的精简版本
  • 是否有自动骨架渲染器之类的东西?就像它会自动将文本变成块等。我不想为每个组件创建一个骨架。
  • 不是全自动的。但是有几个库可以提供帮助。快速谷歌搜索打开这个github.com/dvtng/react-loading-skeleton/blob/master/README.md
【解决方案2】:

编辑

我的理解是,您有一个存储在本地存储中的令牌,并且您正在调度一个操作,然后从该令牌加载用户。加载用户后,您将 isAuthenticated 属性设置为 true。 如果是这种情况,那么浏览器将需要一些时间来获取用户详细信息,因此会暂时显示登录屏幕。在这种情况下,您需要一个加载屏幕,同时调用 api 来获取用户详细信息。

我的建议是将isLoading 状态与isAuthenticated 分开。在进行 api 调用之前将 isLoading 设置为 true,一旦 api 调用完成(成功/失败),然后将 isLoading 设置为 false 并相应地设置 isAuthenticated。 在您的登录组件中检查 isLoading 是否设置为 true,然后显示加载微调器(或其他东西),否则显示您拥有的常规代码。

如果我理解有误,请告诉我。

我的 api 调用通常具有以下效果。

export const useHttp = (url, dependencies) => {

  const [isLoading, setisLoading] = useState(true);
  const [data, setdata] = useState(null);
  useEffect(() => {
    fetch(url)
    .then(response => response.json())
    .then(data => {
      setisLoading(false);
      setdata(data);
    })
    .catch((err) => {
      setisLoading(false);
      console.log(err);
    })
  }, [url,  ...dependencies])

  return [isLoading, data];
}

【讨论】:

  • 我最终这样做了。但是我想知道您是否可以在 api 调用获取用户详细信息时延迟渲染,然后在收到后进行渲染。
猜你喜欢
  • 1970-01-01
  • 2017-05-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多