In my new react-redux app (I'm a newbie to react), I'm using Material-UI and have added material-ui tabs on my web app. The tabs are intended to change the URL upon selection which I achieved using the following piece of code.
function handleActive(tab) {
browserHistory.push(tab.props['data-route']);
}
I want my tabs to show selected tab indicator when I visit the routes manually instead of clicking on the tabs. Which I'm right now not able to figure out. Can anyone suggest me a way to do that either by react or redux? Let me know, If I'm not clear in my question.
UPDATE
Code in my components render()
. There is nothing else in component.
render() {
function handleActive(tab) {
browserHistory.push(tab.props['data-route']);
}
return (
<Paper>
<Toolbar className="navbar">
<ToolbarGroup>
<Link to="/" style={{ textDecoration: 'none' }}>
<ToolbarTitle style={this.styles.title} text="Test App" />
</Link>
</ToolbarGroup>
<ToolbarGroup className="tab-container">
<Tabs className="tabs">
<Tab data-route="/" onActive={handleActive} className="tab" label="Route A" />
<Tab data-route="/routeB" onActive={handleActive} className="tab" label="Route B" />
<Tab data-route="/routeC" onActive={handleActive} className="tab" label="Route C" />
<Tab data-route="/routeD" onActive={handleActive} className="tab" label="Route D" />
</Tabs>
</ToolbarGroup>
</Toolbar>
</Paper>
);
}
I doubt if parsing url is a great idea. Maybe it's better to control tab index from router dispatching action in onEnter
prop of <Route>
?
Let's say you have 2 routes:
<Route path='sign_in' component={AuthenticationWrapper} onEnter={() => { store.dispatch(changeTab(0)) }} />
<Route path='sign_up' component={AuthenticationWrapper} onEnter={() => { store.dispatch(changeTab(1)) }} />
Action creator:
changeTab = (index) => {
return { type: AUTH_TAB_CHANGE, index }
}
Reducer:
authTab = (state = 0, action = {}) => {
switch (action.type) {
case AUTH_TAB_CHANGE:
return action.index
default:
return state
}
}
Component:
class AuthenticationWrapper extends Component {
constructor(props) {
super(props)
this.handleSignIn = this.handleActive.bind(this, '/sign_in')
this.handleSignUp = this.handleActive.bind(this, '/sign_up')
}
handleActive(url) {
browserHistory.push(url)
}
render() {
const { authTab, changeTab } = this.props
return (
<Tabs index={authTab} onChange={changeTab}>
<Tab label='Sign In' onActive={this.handleSignIn}>
<SignInForm />
</Tab>
<Tab label='Sign Up' onActive={this.handleSignUp}>
<SignUpForm />
</Tab>
</Tabs>
)
}
}
const mapStateToProps = ({ authTab }) => {
return {
authTab
}
}
export default connect(mapStateToProps, {
changeTab,
})(AuthenticationWrapper)
Such approach will work both with visiting different urls and changing tabs by clicking on them without refreshing page.
Although there are few ways to do it, Since you're using React Component Class,
You can add componentWillMount
componentWillMount() {
let urlPath = window.location.pathname;
let currentTab = urlPath.split('/').pop();
// you can add more validations here
this.setState({ activeTab: currentTab || 'default' });
}
And in your render
method, change <Tabs className="tabs">
to
<Tabs
className="tabs"
value={this.state.activeTab}
>
<Tab value="default" data-route="/" onActive={handleActive} className="tab" label="Route A" />
<Tab value="routeC" data-route="/routeC" onActive={handleActive} className="tab" label="Route C" />
...
I don't know if this is how we're supposed to set the value
for the Tab
.., But play around with it.
And it should work.
I have used setState
here instead of redux
, As there's nothing wrong in using Component state as long as this is the only component which needs to know which tab is currently active., You can easily change it to use redux
though.
To achieve this, you need to do a couple of things to make sure that you can catch url in the page where tabs are in. Here is what you should do:
<Router history={browserHistory} routes={routes} />
rendered in the div id of your index html. It seems you are doing this since you have browserHistory working. <Tabs className="tabs" value={this is where your this.props.params.name_of_changing_route}>
or in case you have react-router 2.4.0, you can wrap your component with withRouter then you can have access to params, location and route.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With