Настройка частных маршрутов с реагирующим маршрутизатором - PullRequest
0 голосов
/ 07 ноября 2019

Я пытаюсь настроить веб-сайт с экраном входа для неавторизованных пользователей и приборной панелью для авторизованных пользователей, использующих реагирующий маршрутизатор dom.

Каждый раз, когда происходит изменение маршрута (маршрутизации приборной панели), когда пользователь нажимает нассылка на боковой панели, например. Вызывается компонент useEffect внутри панели мониторинга, который извлекает данные, которые у меня уже есть.


## ROUTES ##

export const appRoutes = auth => [
    {
        path: '/',
        component: () => auth ? <Redirect to='/dashboard' /> :<Login/>,
        exact: true
    },
    {
        path: '/dashboard',
        component: Guilds ## REDIRECTS TO THE NEXT ROUTE WITH ID ##,
        exact: true,
        private: true
    },
    {
        path: '/dashboard/:id',
        component: Dashboard,
        private: true
    },
    {
        path: '/dashboard/*',
        component: Dashboard,
        private: true
    }
]

export const dashboardRoutes = [
    {
        path: '/dashboard/:id',
        component: Home,
        exact: true
    }
]

## SIMPLIFIED APP COMPONENT ##

export default function App() {
    return (
        <ThemeProvider theme={theme}>
            <BrowserRouter>
                <Switch>
                    {appRoutes(auth).map(value => {
                        if(value.private) return <PrivateRoute path={value.path} component={value.component} exact={value.exact} key={value.path} auth={auth} />;
                        else return <Route path={value.path} component={value.component} exact={value.exact} key={value.path} />;
                    })}
                </Switch>
            </BrowserRouter>
        </ThemeProvider>
    )
}

## SIMPLIFIED DASHBOARD COMPONENT ## 

export default function Dashboard({ match }) {
    const [guild, setGuild] = useState(null);
    const [user, setUser] = useState(null);

    useEffect(() => {
        getGuild(match.params.id)
        .then(res => {
            setGuild(res.data);
            return getUser();
        })
        .then(res => {
            setUser(res.data);
        })
        .catch(err => {
            console.log(err);
        })
    }, [match.params.id]);

    return (
        <div className={classes.root}>
            <Header onToggleDrawer={onToggleDrawer} guild={guild} auth />
            <SideBar onToggleDrawer={onToggleDrawer} isOpen={drawerOpen} user={user} />
            <div className={classes.content}>
                <div className={classes.toolbar} />
                <div className={classes.contentContainer}>
                    {dashboardRoutes.map(value => {
                        return <Route exact={value.exact} path={value.path} component={value.component} key={value.path}/>
                    })}
                </div>
            </div>
        </div>
    )
}

## PRIVATE ROUTE COMPONENT ##

export const PrivateRoute = ({ component: Component, auth, ...rest }) => {
    return (
        <Route {...rest} render={(props) => (
            auth
                ? <Component {...props} />
                : <Redirect to='/' />
        )} />
    )
}

Я не уверен, правильно ли я подхожу к ситуации, но любая помощь будет полезна. Я так понимаю, эта функция вызывается в том случае, если пользователь заходит на сайт, например, из закладки, но если кто-то может пролить свет на то, что было бы здорово.

Спасибо.

1 Ответ

0 голосов
/ 07 ноября 2019

Причиной, по которой выборка происходит несколько раз, является массив зависимостей, который вы используете для useEffect. Я предполагаю, что match.params.id меняется, когда пользователь щелкает, затем он меняет маршрут, который снова вызывает выборку.

Возможные решения:

1. Пустой массив зависимостей:

Одно из возможных решений может быть, если вы хотите получать данные только после того, как для массива зависимостей будет установлено пустое значение для useEffect. Из документации :

Если вы хотите запустить эффект и очистить его только один раз (при монтировании и размонтировании), вы можете передать пустой массив ([]) каквторой аргумент. Это говорит React, что ваш эффект не зависит от каких-либо значений из реквизита или состояния, поэтому его не нужно повторно запускать.

Поэтому, если у вас есть следующее, оно будет запущено только один раз:

useEffect(() => {
   // this part runs only once
}, []); // empty dependency array

2. Проверка уже произошла выборка:

Другое решение, о котором я думал, это проверить, есть ли у вас значение уже в переменной guild, как показано ниже:

useEffect(() => {
    // no value presented for guild
    if (guild === null) {
       // code which is running the fetch part
    }
}, [match.params.id]);

Я надеюсь, что это дает вам идею и помогает!

...