I'm learning React Router from textbook and facing a problem when changing from Switch
to Routes
with the new function of Lifting State Up. I can't display text after clicking the 'News' link. Here shows the code:
/* index.jsx */
const rootElement = document.getElementById('root');
const root = createRoot(rootElement);
root.render(
<HashRouter>
<Routes>
<Route path='/home' element={<Home />} />
<Route path='/' element={<Home />} />
<Route path='/about' element={<About />} />
<Route path='/news' element={<News />} />
</Routes>
</HashRouter>,
);
/* About.jsx */
<- good code
const About = () => (
<div>
<Menu />
<h1>這裡是關於我們 This is about us.</h1>
</div>
);
export default About;
/* News.jsx */
<- Problem comes in.
const News = () => {
const [news] = useState([
{ id: 1, name: 'News1', describe: 'A wins!' },
{ id: 2, name: 'News2', describe: 'B wins!' },
]);
return (
<div>
<Menu />
<Routes>
<Route path='/news/*' element={<><p>hello!</p><NewsList
news={news} /></>} />
<Route path='newsReader/:id' element={<><NewsReader news ={news} /></>} />
</Routes>
</div>
);
};
export default News;
It should be like this:
I believe the problem lies in <Route path>
but can't find the solution.
The code <NewsList>
and <NewsReader>
is here:
const NewsList = props => (
<ul>
{
props.news.map(theNews => (
<li key = {theNews.id}>
<Link to = {`/news/newsReader/${theNews.id}`}>
{theNews.name}</Link>
</li>
))
}
</ul>
);
export default NewsList;
const NewsReader = (props) => {
const {id:targetNewsId} = useParams();
const targetNews = props.news.find(theNews => (
String(theNews.id) === String(targetNewsId)
));
return(
<div>
<h1>你正在閱讀 You are now reading {targetNews.name}</h1>
<p>{targetNews.describe}</p>
</div>
)
}
export default NewsReader;
Thank you very much for your answer.
CodePudding user response:
For nested routes, you need to follow the below approach
// index.js -> /news/*
const rootElement = document.getElementById('root');
const root = createRoot(rootElement);
root.render(
<HashRouter>
<Routes>
<Route path='/home' element={<Home />} />
<Route path='/' element={<Home />} />
<Route path='/about' element={<About />} />
<Route path='/news/*' element={<News />} /> // here you need to /*
</Routes>
</HashRouter>,
);
For the News.jsx you need to have relative path to /news like below
const News = () => {
const [news] = useState([
{ id: 1, name: 'News1', describe: 'A wins!' },
{ id: 2, name: 'News2', describe: 'B wins!' },
]);
return (
<div>
<Menu />
<Routes>
<Route path='/*' element={<><p>hello!</p><NewsList
news={news} /></>} />
<Route path='newsReader/:id' element={<><NewsReader news ={news} /></>} />
</Routes>
</div>
);
};
export default News;