【问题标题】:ReactJS - Protected routes based on an api call responseReactJS - 基于 api 调用响应的受保护路由
【发布时间】:2021-05-01 20:06:39
【问题描述】:

我正在尝试使用 API 端点实现受保护的路由,但与渲染相比,响应速度较慢。
结果,我的 localStorage 中有正确的数据,但 react 从来没有按时使用它们。

我正在使用 localStorage 来保存我的 API 身份验证响应以及初始状态和一个调度程序来更新我在整个应用程序中的状态。

我从上到下做了什么:

初始状态:

export default {
  auth: {}
};  

App.js

const App = () => {
  const [data, dispatch] = useReducer(reducer, initialState);
  
  useEffect(() => {
    asyncStorage.getItem('data').then((storage) => {
      dispatch({ type: "PERSIST_DATA", payload: JSON.parse(storage) });
    });
  }, []);

  useEffect(() => {
    asyncStorage.setItem('data', JSON.stringify(data));
  }, [data]);
  
  return <Router data={data} dispatch={dispatch} />;
};

Router.js

export default function Router({data, dispatch}) {
  
  return (
    <ProvideAuth data={data} dispatch={dispatch}>
      <BrowserRouter>
        <Switch>
            <PrivateRoute path="/" data={data} dispatch={dispatch}>
              <Home data={data} dispatch={dispatch} />
            </PrivateRoute>
            <Route path="/sign-in" render={() => <Signin data={data} dispatch={dispatch} /> } />
          </Switch>
      </BrowserRouter>
    </ProvideAuth>
  )

} 

function PrivateRoute({ children, ...rest }) {
  const auth = useAuth()
  
  return (
    <Route {...rest} render={({ location }) =>
        auth.loggedIn ? (children) :
        (<Redirect to={{ pathname: '/sign-in', state: { from: location } }} />)
      }
    />
  )
}

Auth.js

const authContext = createContext();

export function ProvideAuth({ children, data, dispatch }) {
  const auth = useProvideAuth(data, dispatch)
  return <authContext.Provider value={auth}> { children } </authContext.Provider>
}

export const useAuth = () => useContext(authContext);

function useProvideAuth(data, dispatch) {
  const [loggedIn, setLoggedIn] = useState(null);
  
  useEffect(() => {
    auth
      .me(dispatch)
      .then(() => {
        setLoggedIn(true);
      })
      .catch(() => {
        setLoggedIn(false)
      });
  }, [])

  return {
    loggedIn
  }

}

auth.me

export function me(dispatch) {
  return api
    .me()
    .then((response) => {
      dispatch({ type: "UPDATE_AUTH", payload: response });
    })
    .catch((error) => {
      throw error;
    });
}

我觉得我快到了,但我可能遗漏了一些明显的东西。

【问题讨论】:

    标签: reactjs react-hooks local-storage


    【解决方案1】:

    没有 1:我相信,您在 App.js 中的第二个 useEffect 可能会几乎每秒运行一次,因为没有指定依赖数组,这可能会影响您期望的更新,因为组件会一直挂载

    No 2:我不知道 Auth.js 中的 auth.me(dispatch) 是做什么的,所以可能很难推断

    【讨论】:

    • 第二次 useEffect 只运行一次。比方说,在浏览器刷新后,我找不到另一种将数据保存在存储中的方法。 auth.me 从 API 请求并通过电子邮件更新 localStorage 状态。
    • 既然如此,何不先console.log(auth.loggedIn) 看看是假还是真。您可以确认您的状态是否真正更新为 true
    • 确实如此,正如我所提到的,问题是它在页面重定向到登录后才出现。
    • 我无法真正给出最佳解决方案,因为我看不到有效的工作代码但我认为这应该有效如果您在重定向到登录页面后让 auth.loggedin 为真,我认为你只需要在登录页面中添加一个useEffect,检查auth.logged in 是否为真并重定向到主页
    • 如果我只是将相同的逻辑放在 SignIn 组件后面,它会在每次导航点击后重定向到登录表单上。我很惊讶没有通用的方法来做到这一点。
    猜你喜欢
    • 1970-01-01
    • 2019-08-31
    • 2022-11-16
    • 2021-07-19
    • 2021-09-18
    • 2018-08-09
    • 2017-08-10
    • 2020-10-04
    相关资源
    最近更新 更多