Tomas Bui
Tomas Bui

Reputation: 51

React update url base on action

I'm new to ReactJS. I have a problem with React Router v4 and need some advice from you guys. In my application (React + Redux), I'm configuring my route:

/app/:appId/detail
/app/:appId/config/:store
/app/:appId/gifts

And render 2 components at the same time. A select component (allow change appId) and a main component (showing data).

Suppose that I'm in /app/1/detail with appId is 1 and showing a detail from application 1. When I press change application to 2, I want to change my url like /app/2/detail and change data to application 2 by the time. (means matching :appId to 2)

I know that I can dispatch an action with Redux then DetailComponent (or ConfigComponent/GiftsComponent) can catch it and change manual from inside component (every component) by using history.push or history.replace. My application have a lot of components, manual handling can increase complexity in my app, so it is not a good way to resolve it.

Help me if having any solution. Thank you very much.

Upvotes: 5

Views: 17320

Answers (2)

Cagri Yardimci
Cagri Yardimci

Reputation: 3539

So you mentioned that

A select component (allow change appId) and a main component (showing data).

And also state that you are worried about the following:

My application have a lot of components, manual handling can increase complexity in my app, so it is not a good way to resolve it.

So maybe you should go with wrapping this select component with withRouter HOC first as it is already mentioned, if this select component is used more than once.

Wrapping would allow you to access the following props =>

props: { match, location, history }

match object also contains params and url. Url stores the value of current path. In your case it basically is /app/1/detail. Params stores the parameters that the route has. In your case params would be the following params { appId: 1 } Having access to these props would allow you to implement and maintain routing logic inside of a single component.

So if you use a dropdown menu you can do the following

import React from 'react';
import { Link, withRouter } from 'react-router-dom'

const SelectComponent = ({match: {params, url}}) => (
  <div>
    dropDownItems.map(item => 
       <Link 
        key={item.id // or simply item.appId}
        to={url.replace(`${params.appId}`, `item.appId`)
       >
        Change application to {item.appId}
      </Link>
    </div>
)

export default withRouter(SelectComponent)

Since params.appId corresponds to '1' and I assume that there won't be any parameter that equals to the value of appId, url.replace(...) would basically replace the value of former appId with the new value in the url.

So any change should redirect you to the new route with the updated appId

If you use buttons you can also use <Link /> to wrap your button I guess, but you could also use history.push method as an onClick event to handle the redirection.

Upvotes: 6

Henrique Coura
Henrique Coura

Reputation: 852

Although your question is not clear, it seems you want to change the current url programmatically with react-router.

For this you will need the withRouter HOC from react-router. With it you can do something like this:

import React from 'react';
import PropTypes from 'prop-types';
import {withRouter} from 'react-router';

const ExampleComponent = (props) => {

  const goToNextId = () => {
    props.history.push(`/app/${props.match.params.appId + 1}/detail`);
  };

  return (
    <div>
      <button onClick={goToNextId}>Next Id</button>
    </div>
  );
};

ExampleComponent.propTypes = {
  history: PropTypes.object.isRequired,
  match: PropTypes.object.isRequired,
};

export default withRouter(ExampleComponent);

Upvotes: 1

Related Questions