Alan Willian Duarte
Alan Willian Duarte

Reputation: 134

How to limit reactjs useContext for only some routes from react-router

I want to be able to pass some contexts only for some pages, but the way react-router is made I can't find out how to do that. For example, I want to AlertsProvider to be available only to alerts screen, GroupsProvider to be available only for groups screen and so on

How can I do this?

Here is the code I have right now:

<React.StrictMode>
  <GlobalStyle />
  <BrowserRouter>
    <AuthProvider>
      <PropertiesProvider>
        <BuyersProvider>
          <AlertsProvider>
            <GroupsProvider>
              <Switch>
                <PrivateRoute path="/" exact component={Dashboard} />
                <Route path="/login" exact component={Login} />
                <Route path="/recover_password" exact component={RecoverPassword} />
                <PrivateRoute path="/imoveis" exact component={Properties} />
                <PrivateRoute path="/compradores" exact component={Buyers} />
                <PrivateRoute path="/grupos" exact component={Groups} />
                <PrivateRoute path="/alertas" exact component={Alerts} />
                <PrivateRoute path="/relatorios" exact component={Reports} />
              </Switch>
            </GroupsProvider>
          </AlertsProvider>
        </BuyersProvider>
      </PropertiesProvider>
    </AuthProvider>
  </BrowserRouter>
</React.StrictMode>

Upvotes: 2

Views: 1420

Answers (1)

gerrod
gerrod

Reputation: 6637

Why can't you just add the relevant providers around their corresponding route components? e.g. -

<Switch>
    <PrivateRoute path="/alertas" exact>
        <AlertsProvider>
            <Alerts />
        </AlertsProvider>
    </PrivateRoute>
</Switch>

Edit: After you comment clarifying that some routes need to share a context - I guess another approach you could use is to just separate them out into multiple Switch statements - you don't need to have everything in one. Obviously I don't know all your particular use cases but you could do something like this -

<BrowserRouter>
    <AuthProvider>
        <PropertiesProvider>
            <Switch>
                <Route path="/" exact component={Dashboard} />
                <PrivateRoute path="/imoveis" exact component={Properties} />
            </Switch>
        </PropertiesProvider>

        <AlertsProvider>
            <Switch>
                <PrivateRoute path="/alertas" exact component={Alerts} />
                <PrivateRoute path="/relatorios" exact component={Reports} />
            </Switch>
        </AlertsProvider>
    </AuthProvider>
</BrowserRouter>

The downside to this approach is that you're still rendering the PropertiesProvider and AlertsProvider even if you don't actually need them (though this does solve your issue of not making them available to child components that shouldn't have access to them). You can solve this with a bit more plumbing, though -

<BrowserRouter>
    <AuthProvider>
        <Switch>
            <Route exact path={["/", "/imoveis"]}>
                <PropertiesProvider>
                    <Route exact path="/" component={Dashboard} />
                    <PrivateRoute path="/imoveis" component={Properties} />
                </PropertiesProvider>
            </Route>

            <Route exact path={["/alertas", "/relatorios"]}>
                <AlertsProvider>
                    <PrivateRoute path="/alertas" component={Alerts} />
                    <PrivateRoute path="/relatorios" component={Reports} />
                </AlertsProvider>
            </Route>
        </Switch>
    </AuthProvider>
</BrowserRouter>

Upvotes: 5

Related Questions