Создайте защищенный маршрут в React на основе состояния

#reactjs #react-router

#reactjs #react-маршрутизатор

Вопрос:

Я пытаюсь создать маршрут, к которому могут получить доступ только люди с определенной ролью. Эта роль устанавливается в состоянии (я использую redux) после входа пользователя в систему, однако кажется, что компонент Private Route получает только начальное состояние. Мне нужен компонент PrivateAdminRoute для обновления при изменении состояния, и, похоже, он этого не делает. Это мой App.js:

 function App() {
  const dispatch = useDispatch();
  const loggedInData = useSelector(state => state.loggedInData.loggedIn);

  useEffect(() => {
    axios.get('/api/users/current')
      .then(res => {
        if (res.data === "") {
          dispatch(signOut());
        } else {
          dispatch(signIn(res.data.role, res.data.firstName));
        }
      });
  }, [dispatch]);

  return (
    <div className="App">
      <NavBar />
      <Switch>
        <PrivateAdminRoute path="/admin" component={Admin} role={loggedInData.role} />
      </Switch>
    </div>
  );
}

export default App;
 

И это мой компонент PrivateAdminRoute:

 const PrivateAdminRoute = (props) => {
    return <Route path={props.path} render={(props) => (
                    props.role === 'Admin' ? <Admin /> : <Redirect to='/' />
                )}
            />
}

export default PrivateAdminRoute;
 

И вот мой редуктор:

 const loggedReducer = (state = initialState, action) => {
    switch(action.type) {
        case 'SIGN_IN':
            return {
                ...state,
                loggedIn: {
                    isLogged: true,
                    role: action.payload.role,
                    username: action.payload.name
                }
            }
        case 'SIGN_OUT':
            return {
                ...state,
                loggedIn: {
                    isLogged: false,
                    role: "None",
                    username: ""
                }
            }
        default:
            return state;
    }
}
 

Любая помощь будет оценена!

Комментарии:

1. Это вызвано вашими затененными именами параметров? У вас есть props для PrivateAdminRoute компонента, а затем у вас есть props снова для render свойства Route компонента. props предоставленный для render функции, имеет только свойства, предоставленные маршрутизатором, и не включает те, которые предоставлены вашему PrivateAdminRoute компоненту.

2. Это хорошая уловка — вы знаете, как я должен передать props то, что я хочу, в функцию рендеринга? Я изменил имя того, что я передавал, но это не решило мою текущую проблему.

3. Достаточно было просто изменить имя одного из параметров, а затем получить доступ к свойству с использованием правильного имени, если бы это было проблемой. Обычно я бы попытался свести к минимуму количество анонимных функций и вместо выполнения подкачки при рендеринге маршрута сделать что-то еще в духе props.role === 'Admin' ? <route path={props.path} component={Admin} /> : <Redirect to="/" /> . Вы убедились, что значение было обновлено в Redux и что вы создаете новое состояние, а не обновляете старое состояние?

4. Похоже, что ваш редуктор должен функционировать так, как вы ожидаете. Я создал быстрый пример тестового примера, используя useReducer вместо хранилища redux, и, похоже, он функционирует так, как вы ожидаете: stackblitz.com/edit/react-ts-ebbpws?file=index.tsx

5. Ввод правильного URL-адреса заставил бы его проверять роль и перенаправлять перед загрузкой пользователя. Вам нужно будет добавить состояние загрузки и не отображать маршруты до тех пор, пока пользователь не войдет в систему.