Re-using a react component across different routes - react-router

We ran into a situation where we have edit page and create page sharing the same component. The router looks like below.
<Route path="/" component={AdrApp}>
<IndexRoute component={ManageDrugPage}/>
<Route path="cdicms-adr-ui" component={HomePage}/>
<Route path="create-adr" component={ManageADRTermPage}/>
<Route path="manage-adr/:id" component={ManageADRTermPage}/>
As we see above the 'ManageADRTermPage' component is used by 'create-adr' route and 'manage-adr' route.
The problem with this is that we have a dropdown component implemented using react-bootstrap.
When the user is in the edit page and the user now selects the create page the page is not transitioning. The edit page stays right there. we do this.history.pushState(null, '/create-adr') when the 'create' dropdown is clicked.
How could we workaround this issue?

Easy workaround would be to have a simple CreateADRTermPage component, that's a wrapper for your ManageADRTermPage.
Or change your ManageADRTermPage component to EditADRTerm, and have both CreateADRTermPage and ManageADRTermPage be simple wrappers of it.

Related

Anchor links working locally but not when deployed (React)

I have a one page react app and I have a menu with anchor links set up like this:
Story
And in the target div, I have it like this:
<div id="story" class="py-16 xl:py-36 px-4 sm:px-6 lg:px-8 bg-black overflow-hidden">
When I do npm start to run the page locally, the anchor links work as intended. When I deploy it to the web, the links give me a 404.
Why would this happen?
EDIT:
I read about react-router-dom and tried to implement it, but I am getting strange behavior.
I imported this at the top of App.js:
import {
BrowserRouter as Router,
Switch,
Route,
Link
} from "react-router-dom";
I wrapped the enter contents of the first App() function in <Router></Router>.
Then inside the App() section, I set up this:
<Switch>
<Route path="/about">
<About />
</Route>
</Switch>
My About link is set up like this:
<a href="/about" class="text-base text-gray-300 hover:text-white">
About
</a>
Then at the very bottom of the App.js document, below the , I have this:
function About() {
return (
<><h2>About</h2>
<br />
<p>Test</p></>
);
}
But what happens when I click the About link is it re-renders the entire main page and the text "About Test" at the bottom.
What do I need to do to get this to render as an entirely new page?
As far as I am aware you can not use <a> tags for internal navigation in react. I don't know why it works locally for you.
With react you are creating single page applications (SPAs), you have 1 html page that can be found in the public folder. If you created the app using create-react-app, you will see within it, an element such <div id=root> </div>. That is the targetted rendering location, where you will be rendering the entire app by dynamically changing the html within it as you interact with the page.
However, when you typically click on an <a> tag, we are usually taken to different html page. Here I would assume the server is trying to retrieve either the App.html page or index.html page from within public/App folder.
React does not typically come in with built in routing functions/components. It leaves it up to the user to implement. So user's usually turn to a package like react-router along with react-router-dom/native (depending on react or react native) to get those functionalities.
Answer to Updated Question
Change your <a> tags to <Links> as follows
<Link to='/about' className='tailwind_classes'>About</Link>
<Link> tags are meant to replace <a> tags if using react-router-dom for navigation.
When you click on it, your <Router> is notified and lets the <Switch> figure out which <Route> to render
Update
Okay let's say you have a header where your links are, and we have 2 components <Home> and <About>
Then this is how your <App> should look like
return(
<Router>
{/* The header can be it's own component*/}
<header>
<Link to='/home' className='tailwind_classes'>Home</Link>
<Link to='/about' className='tailwind_classes'>About</Link>
</header>
<Switch>
{/* exact makes sure path has to be exactly '/' */}
<Route exact path="/">
<Home />
</Route>
<Route path="/about">
<About />
</Route>
</Switch>
<Router>
)
You could obviously write the markup for the <Home> & <About> component directly inside the <Route>s but would not advise. The header can also be it's own component and it will always stay on the screen since it is outside the switch, making it kind of a global thing.
The to prop of Link must match the path prop of one of the Route
Basically when you click on a link, the url changes. The Router is notified who then passes the new url to the Switch, which then acts like a switch case statement to match the url and renders/mounts the JSX inside the matched Route after removing/unmounting what was previously there.
Read the read the react-router-dom documentation for further clarification

React Router with mix of Fixed Routers and Dynamic Route

I am having routes like
/: Login
/A: A Component
/:[dynamic] : B Component
Now I am using code Like below, but now every time Component B is loading, even if i pass "Exact" keyword too.
<Route exact path="/">
<LoginComponent />
</Route>
<Route exact path="/:dynamic" component="Dynamic' />
<Route exact path="/A" component="A" />
this happens because the router can not distinguish between the dynamic value or "A" or "".
as I know you can't solve it without make another route for B component, like "/basicPath/:dynamic"

React-Router out of sync with window.location?

I'm having trouble getting client-side routing to work properly (with react-router-dom#5.2.0)
I have an <Application> component which returns:
<BrowserRouter>
<Switch>
<Route path="/:filter/:id">
<Something...>
</Route>
<Route path="/">
<SomethingElse...>
</Route>
</Switch>
</BrowserRouter>
Whenever I navigate to [localhost]/rating/good, things work as expected: the proper route is matched (ie. "/:filter/:id") and the <Something> component is rendered.
I have a button which clears what I call filters; whenever I click on it:
I update the URL with useHistory().push('/')
The change is immediately observed
I update of my AppState, which triggers an update of my <Application> component, which in turn means <BrowserRouter> and <Route> are updated.
And that's when I observe something I didn't expect:
The same route as before (ie. path="/:filter/:id") is matched and the <Something> component is rendered -- despite the current URL pathname being "/".
Is this the expected behavior?
If yes, what is react-router using to match routes if not the current window.location?
Now I've got it to work (I think) by updating <Application> with:
const location = { ...useLocation(), pathname: window.location.pathname }
And passing that location object as such:
<Switch location={location}>
But it feels like I'm doing something wrong and that it should have worked without me fiddling with the location object.
Thanks for any hints!

Which of the following is the correct way to create links for the react components?

1. <a href={‘https://www.facebook.com/’}>Link1</a>
2. <a link-to={testContainer}>Link1</a>
3. <a href={[to-component]}>Link1</a>
4. <a href-to={‘https://www.facebook.com/’}>Link1</a>
Sorry, but I am confused which is the correct answer. Which and why?
You can try it in your React app.
It's a correct HTML attribute for React
<a link-to={testContainer}>Link1</a>
One of the options not mentioned in your question is using react-router for routing needs. This would involve creating routes which would be later used to navigate the different components. The example below shows a sample Router.
<Router >
<Route path="/" component={Root}>
<Route path="home" component={Home}/>
</Route>
</Router>
You can use the Link object to create dynamic links which would navigate to the appropriate component.Using the above example, this would look like
<Link to="/home">Home</Link>

Cannot GET /profile in React Routing

Im fiddling with React routing and I have just two different components. When I try to render my second component I get Cannot GET /profile
My routing looks like this
render((
<Router history={browserHistory}>
<Route path="/" component={Main}>
<Route path="/profile" component={Profile}/>
</Route>
</Router>
), document.getElementById('app'))
but my /profile component returns the error message when I visit localhost:3000/profile
Do I need to put render them from another component, or what seems to be the issue?
Remove the / from /profile, it should work. You don't have to explicitly prepend / if it is already in the parent route.