4

I'm using semantic-ui's Tab component and I have different components in each tab's pane. When I click on a tab, I would like the URL to change to "/tabname" so that a specific tab can be bookmarked by users who only need the functionality in that tab.

All the examples on the semantic-ui site define tabs like the code below.

const panes = [
  { menuItem: 'Component 1', render: () => <Tab.Pane><Component1 /></Tab.Pane> },
  { menuItem: 'Component 2', render: () => <Tab.Pane><Component2 /></Tab.Pane> }
]

render() {
  return (
    <Tab panes={panes} />
  )
}

I tried changing the menuItem to:

{ menuItem: () => <NavLink to="/component2">Component 2</NavLink>, render: () => <Tab.Pane><Component2 /></Tab.Pane> }

Or this:

{ menuItem: () => <Menu.Item as={Link} to="/component2">Component 2</Menu.Item>, render: () => <Tab.Pane><Component2 /></Tab.Pane> }

and while it does make the link change, it also disables the tab switching (so clicking the 'Component 2' tab adds '/component2' to the URL, but <Component1 /> is still displayed in the pane). The issue is that the Tab's onClick event is overridden by Link's onClick event, so it breaks the tab switching.

There has to be a way to make a tab change the link AND change the pane content. The component augmentation feature of semantic-ui-react is supposed to solve these kinds of issues but it seems to fail with the Tab component. If only their documentation would not be paper thin.

2 Answers 2

4

Here is a similar question answered.

https://github.com/Semantic-Org/Semantic-UI-React/issues/3935

The sample code is here:

https://codesandbox.io/s/react-example-5jtuo?file=/index.js

I don't know how code snippet works. I prefer using code sandbox. If someone wants to fix the snippet and share, that would be awesome. I just coppied the code over so it is visible in case code sandbox goes down in the future.

import "react-app-polyfill/ie11";
import "react-app-polyfill/stable";
import ReactDOM from "react-dom";
import React, { Component } from "react";
import { Tab } from "semantic-ui-react";
import {
  BrowserRouter as Router,
  Route,
  NavLink,
  Switch
} from "react-router-dom";

import "semantic-ui-css/semantic.min.css";

class App extends Component {
  render() {
    const panes = [
      {
        menuItem: {
          as: NavLink,
          id: "tab1",
          content: "Home",
          to: "/",
          exact: true,
          key: "home"
        },
        pane: (
          <Route
            path="/"
            exact
            render={() => (
              <Tab.Pane>
                <div>Home</div>
              </Tab.Pane>
            )}
          />
        )
      },
      {
        menuItem: {
          as: NavLink,
          id: "tab2",
          content: "Authentication",
          to: "/auth",
          exact: true,
          key: "auth"
        },
        pane: (
          <Route
            path="/auth"
            exact
            render={() => (
              <Tab.Pane>
                <div>Authentication content here</div>
              </Tab.Pane>
            )}
          />
        )
      },
      {
        menuItem: {
          as: NavLink,
          id: "tab3",
          content: "Config Lists",
          to: "/configs",
          exact: true,
          key: "configs"
        },
        pane: (
          <Route
            path="/configs"
            exact
            render={() => (
              <Tab.Pane>
                <div>Config Lists content here</div>
              </Tab.Pane>
            )}
          />
        )
      }
    ];

    return (
      <Router>
        <div className="App" style={{ margin: "50px" }}>
          <Switch>
            <Tab renderActiveOnly={false} activeIndex={-1} panes={panes} />
          </Switch>
        </div>
      </Router>
    );
  }
}

ReactDOM.render(<App />, document.getElementById("root"));
<link href="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/1.11.8/semantic.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/react-router-dom/umd/react-router-dom.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui-react/1.2.0/semantic-ui-react.min.js"></script>
<div id="root"></div>

Sign up to request clarification or add additional context in comments.

Comments

0

You should try this:

const panes = [
  { menuItem: 'Component 1', render: () => <Tab.Pane as="NavLink" to="/component1"><Component1 /></Tab.Pane> },
  { menuItem: 'Component 2', render: () => <Tab.Pane as="NavLink" to="/component2"><Component2 /></Tab.Pane> }
]

render() {
  return (
    <Tab panes={panes} />
  )
}

1 Comment

It unfortunately doesn't work. It wraps the content of the pane in the rendered NavLink's <a> tag. I might be doing something wrong because my routes ``` <Route path="/component1" component={Component1} /> ``` also render a copy of the component below the pane. So there is a copy in the pane wrapped by the NavLink and another one below the pane. I think I just need to read more sample code from tutorial and I'll figure out what I'm doing wrong.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.