React -router doesn't add component to the dom
I have Quotes
component which contains list of quotes. When I click individual list element, react router changes the url dynamically and opens it in full page which is Full_Screen_Quotes
then again inside the Full_Screen_Quotes
I want to add Comments
section on button click with the help of react router, but it does not work for the reason I do not know. What might be the reason?
import { useParams } from "react-router-dom/cjs/react-router-dom.min"
import Comments from "./Comments"
import classes from '../css/Full_Screen_Quote.module.css'
import db from "./db"
import { useState } from "react"
import { Router,Route } from "react-router-dom/cjs/react-router-dom.min"
import { Link } from "react-router-dom"
import { Switch } from "react-router-dom/cjs/react-router-dom.min"
const Full_Screen_Quotes = ()=>{
const params = useParams()
return(
<>
<div className={classes.quote}>
<h1>{params.quoteId} </h1>
<h4>{params.authorId}</h4>
<Link to = {`/Allquotes/${params.authorId}/${params.quoteId}/comments`}> // Link that adds comment section
<button>ADD</button>
</Link>
</div>
<Route path ={`/Allquotes/${params.authorId}/${params.quoteId}/comments` } exact > //Comment section path
<Comments></Comments>
</Route>
</>
)
}
export default Full_Screen_Quotes
App js
import logo from './logo.svg';
import './App.css';
import {Route} from 'react-router-dom'
import {Switch} from 'react-router-dom'
import {Link} from'react-router-dom'
import MainHeader from '../src/components/MainHeader'
import Quotes from '../src/components/Quotes'
import AddQuotes from './components/AddQuotes';
import Welcome from './components/Welcome'
import {useParams} from 'react-router-dom'
import ListElement from './components/ListElement';
import Full_Screen_Quote from '../src/components/Full_Screen_Quote'
import {Redirect} from 'react-router-dom'
import Home from '../src/components/Home'
import NotFound from './NotFound';
import {useState,useCallback,useMemo} from 'react'
import { Prompt } from 'react-router-dom/cjs/react-router-dom.min'
import Comments from './components/Comments';
function App() {
const [is_focused,set_is_focused] = useState(false)
return (
<div>
<Switch>
<Route path ='/Welcome/' exact>
<Welcome/>
</Route>
<Route path ='/Allquotes/' exact>
<Quotes />
</Route>
<Route path ='/Addquote/' exact>
<AddQuotes set_is_focused = {set_is_focused} is_focused={is_focused} />
</Route>
<Route path ='/Allquotes/:authorId/:quoteId' exact>
<Full_Screen_Quote />
</Route>
</Switch>
</div>
)
}
export default App;
Comments js
import { useState } from "react"
import db from '../components/db'
import { useRef } from "react"
const Comments = (props)=>{
return (
<div style={{display:'flex',justifyContent:'center'}}>
<div> <textarea style={{transition:'1s all'}}></textarea> </div>
</div>
)}
export default Comments
Your root router/Switch
is exactly matching URL paths, and in the case of rendering the Full_Screen_Quote
component it only exactly matches up to '/Allquotes/:authorId/:quoteId'
<Route path ='/Allquotes/:authorId/:quoteId' exact>
<Full_Screen_Quote />
</Route>
As soon as the path becomes "/Allquotes/someAuthorId/someQuoteId}/comments" it no longer matches exactly and your Full_Screen_Quote
component is unmounted, thus unmounting the nested Route
you want to render for the Comments
component.
In 99.99% for use cases there's really no need to use the exact
prop in conjunction with the Switch
since you can order the rendered routes in inverse order of path specificity so matching can work properly. Using the exact
prop also necessarily precludes the further matching of any nested routes.
You've a couple options:
-
Order the routes in the
Switch
in descending path specificity order and remove theexact
prop. This allows the nested route inFull_Screen_Quote
to be eventually matched and rendered.<Switch> <Route path='/Welcome/'> <Welcome /> </Route> <Route path='/Allquotes/:authorId/:quoteId'> <Full_Screen_Quote /> </Route> <Route path='/Allquotes/'> <Quotes /> </Route> <Route path='/Addquote/'> <AddQuotes set_is_focused={set_is_focused} is_focused={is_focused} /> </Route> </Switch>
...
const Full_Screen_Quotes = () => { const { path, url } = useRouteMatch(); const params = useParams(); return ( <> <div className={classes.quote}> <h1>{params.quoteId} </h1> <h4>{params.authorId}</h4> <Link to={`/${url}/comments`}> <button>ADD</button> </Link> </div> <Route path={`${path}/comments`}> <Comments /> </Route> </> ); };
-
Move the nested route out to the main router/
Switch
and order the routes in descending path specificity order and remove theexact
prop.<Switch> <Route path='/Welcome/'> <Welcome /> </Route> <Route path='/Allquotes/:authorId/:quoteId/comments'> <Comments /> </Route> <Route path='/Allquotes/:authorId/:quoteId'> <Full_Screen_Quote /> </Route> <Route path='/Allquotes/'> <Quotes /> </Route> <Route path='/Addquote/'> <AddQuotes set_is_focused={set_is_focused} is_focused={is_focused} /> </Route> </Switch>
...
const Full_Screen_Quotes = () => { const { url } = useRouteMatch(); const params = useParams(); return ( <div className={classes.quote}> <h1>{params.quoteId} </h1> <h4>{params.authorId}</h4> <Link to={`/${url}/comments`}> <button>ADD</button> </Link> </div> ); };