Thanks to everyone for your efforts to help me before at How to pass and retrieve data over the url in React I don't know why it wasn't working but I decided to simplify things and just pass a string instead of an object but it still isn't being read. Instead of having a dynamic url, it just passes the string ":i" or ":book.id" or whatever value I try to use in the Link tag.
App.js
<Router>
<div className="App">
<Header />
<Switch>
<Route path="/" component={Main} />
<Route path='/:i' component={Single} />
</Switch>
</div>
</Router>
Main.js
const Main = () => {
return (
<div id="main">
{data.map((book, i) => {
return (
<div key={i} className="squares">
<img
src={images[book.picture]}
className="covers"
alt="book cover"
/>
<h3>
///////////////////////!!! HERE !!!/////////////////////////////////////
**<Link to="/:i">{book.title}</Link>**
</h3>
Book.js
const Book = (props) => {
let id = useParams();
console.log("1", id); ////logs ':i'
You should not pass params in Link like this.
You pass parameter value, like id.
<Link to={`/${i}`}>
And then in route you receive it
<Switch>
<Route path="/:id" children={<Child />} />
</Switch>
Here is doc with examples
Related
I am trying to pass a symbol in the state so that I can render a slug page based on the prop. I am havving issues passing the state in as it breaks everything. I am using react-router-dom to navigate the pages. I have a Link in another file to connect the slug pages.
App.js
function App() {
return (
<div>
<AuthContextProvider>
<Navbar/>
<Routes>
<Route path='/' element={<Home/>}/>
<Route path='/showinvestments' element={<Protected><ShowInvestments/></Protected>}/>
<Route path='/addinvestments' element={<Protected><Add/></Protected>}/>
<Route path='/sell/:stockSell' element={<Protected><Sell ticker={this.state.symbol}/></Protected>}/>
<Route path='/login' element={<Login/>}/>
</Routes>
</AuthContextProvider>
</div>
);
}
The Link to the slug page
....
<div className='col text-center d-flex ' >
<Link to={{pathname: sellLink, state: {symbol: ticker}}}>
<AiFillEdit className='mt-2'/>
</Link>
</div?
....
The page that I am trying to render based on the props passed in
const Sell = ({ticker}) => {
// const {state} = useLocation();
// const { tic } = state;
// console.log(tic);
return (
<div className='container'>
Hello
{ticker}
</div>
)
}
Any help would be appreciated.
I have tried different variants inside of <Route>. If I pass a string as the ticker, it prints that, I just cannot get it to pass the current state in.
Trying to teach myself react and stuck on one part... I can't seem to get page specific content to display based on URL using useLocation() -- HELP!
App.js - router displays page on click, yay!
<Router>
<Routes>
<Route exact path="/" element={<Home />} />
<Route path="/project/projectOne" element={<Project />} />
<Route path="/project/projectTwo" element={<Project />} />
</Routes>
</Router>
Project.js - Project template serves up the components as expected
const Project = () => {
return (
<div className='content-wrapper'>
<Scroll />
<ProjectIntro />
<ProjectContent />
<ProjectGrid />
<Contact />
</div>
); }; export default Project;
ProjectIntro.js - A component trying to serve up the content -- this is where I'm stuck, useLocation() see's the path, but I can't figure out how to show the "projectIntroDetails" based on that path.
const projectOne = () => {
<h1 className='project-intro-heading'>Title Here</h1>,
<figure className='project-intro-image'>
<img src={projectImage} alt='placeholder'/>
</figure>
}
const projectTwo = () => {
<h1 className='project-intro-heading'>Title Here</h1>,
<figure className='project-intro-image'>
<img src={projectTwoImage} alt='placeholder' />
</figure>
}
const projectIntroDetails = {
projectOne: {
component: <projectOne />
},
projectTwo: {
component: <projectTwo />
}
}
const ProjectIntro = () => {
const projectPath = useLocation();
console.log(projectPath);
// this is where I need help
// how do I turn the path into seeing details to render the correct content?
const projectIntroDetail = projectIntroDetails[projectPath.pathname.split("/project/")];
return (
<div className='project-intro'>
{projectIntroDetail}
</div>
);
}; export default ProjectIntro;
You can use a component with a switch statement to determine which child component to render. This method allows you to pass any additional props to the child components.
If you don't need the <div className='project-intro'> element, you could also render the switch directly inside your ProjectIntro component.
const ProjectOne = () => {
<h1 className='project-intro-heading'>Title Here</h1>,
<figure className='project-intro-image'>
<img src={projectImage} alt='placeholder'/>
</figure>
}
const ProjectTwo = () => {
<h1 className='project-intro-heading'>Title Here</h1>,
<figure className='project-intro-image'>
<img src={projectTwoImage} alt='placeholder' />
</figure>
}
const ProjectIntros = ({ slug, ...props }) => {
switch(slug) {
case 'projectOne':
return <ProjectOne {...props} />;
case 'projectTwo':
return <ProjectTwo {...props} />;
default:
return null;
}
}
const ProjectIntro = () => {
const projectPath = useLocation();
console.log(projectPath);
return (
<div className='project-intro'>
<ProjectIntros slug={projectPath.pathname.split("/")[2]} />
</div>
);
}; export default ProjectIntro;
You don't really need to use the useLocation hook or pathname value to handle any conditional rendering logic, that's what the routing components are for.
I would suggest either passing in the correct sub-project component as a prop to be rendered on the correctly matching route, or refactoring the routes to do this in a more "react router" way.
Passing component down as prop example:
App
<Router>
<Routes>
<Route path="/" element={<Home />} />
<Route
path="/project/projectOne"
element={<Project projectIntro={<ProjectOne />} />}
/>
<Route
path="/project/projectTwo"
element={<Project projectIntro={<ProjectTwo />} />}
/>
</Routes>
</Router>
Project
const Project = ({ projectIntro }) => {
return (
<div className='content-wrapper'>
<Scroll />
<div className='project-intro'>
{projectIntro}
</div>
<ProjectContent />
<ProjectGrid />
<Contact />
</div>
);
};
Using react-router-dom to your advantage.
Project
Convert Project into a layout component and render the ProjectOne and ProjectTwo components on nested routes. Layout routes are intended to be used to share common UI elements and layout, and render routed content into an outlet.
import { Outlet } from 'react-router-dom';
const Project = () => {
return (
<div className='content-wrapper'>
<Scroll />
<div className='project-intro'>
<Outlet /> // <-- render nested routes here
</div>
<ProjectContent />
<ProjectGrid />
<Contact />
</div>
);
};
App
<Router>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/project" element={<Project />}>
<Route path="projectOne" element={<ProjectOne />} />
<Route path="projectTwo" element={<ProjectTwo />} />
</Route>
</Routes>
</Router>
I want to add routing to my app but the "Link" I made in a child component doesn't work onClick, but only when I refresh the page. I guess the problem is the way too much nesting but I have no idea how can I solve it.
One mention: I imported BrowserRouter as Router everywhere.
This is the file structure
This is the code spippets that related to my problem:
App component:
function App() {
return (
<Router >
<div className="App">
<Switch>
<Route exact path="/" component={NewFetch} />
<Route path="/cardID/:id" component={Details} /> //The route that doesn't work
</Switch>
</div>
</Router>
NewFetch (Main) component:
<Router> //Tried with <React.Fragment>
...
<Route path={["/cards/:name", "/cards/:filter"]}>
<Filter isLoaded={isLoaded} handleScroll={handleScroll} toScrollTop={toScrollTop} value={value}
scrollPosition={scrollPosition} jumpToTop={jumpToTop} testFilter={testFilter} />
</Route>
</Router>
Card (child 2) component from :
const Card = (props) => {
return (
<div className={props.img ? "card" : "hide"}>
<Link to={`/cardID/id=${props.id}`} > //Link that doesn't connect
<img src={props.img} alt={props.name} />
</Link>
</div>
)
};
So basically I can't connect the "Link" from a hardly nested component.
function App() {
return (
<Router >
<div className="App">
<Switch>
<Route exact path="/" component={NewFetch} />
<Route path="/cardID/:id" component={Details} /> //The route that doesn't work
</Switch>
</div>
</Router
const Card = (props) => {
return (
<div className={props.img ? "card" : "hide"}>
<Link to={`/cardID/id=${props.id}`} > //Link that doesn't connect
<img src={props.img} alt={props.name} />
</Link>
</div>
)
};
Above is your code which might look right but the is a slight bug here:
The bug is in the wrong way you are linking to path="/cardID/:id
What you are to do is in your Card child2 is:
const Card = (props) => {
return (
<div className={props.img ? "card" : "hide"}>
<Link to={`/cardID/${props.id}`} > //Removed **id=....**
<img src={props.img} alt={props.name} />
</Link>
</div>
)
};
This is what you have to understand that when you make a route like so path="/route/:id" the :id is just a placeholder waiting for you to place anything so id is commonly used so your code makes sense and mainly basically you want to route based on id but one could have written :cat for example but that is just a placeholder
I have:
<Switch>
<Route
exact
path={'/path/to/my/component'}
component={MyComponent}
/>
...
</Switch>
MyComponent:
return (
<div>
<h1>Here Some Text</h1>
<Link to={'/path/to/my/component/test'}>Test</Link>
<Route exact path={"/path/to/my/component/test"} component={MyOtherComponent} />
</div>
)
I am able to render MyComponent, but when I click on the link to .../test route it does not render the route below. It goes to a 404 page that I have defined.
Am i missing something?
--
So, after testing some answers, i got a problem that, the route that the link is redirecting to, does not display.
Given the following code (be aware that, all this code is already a route and is inside a <switch>).
render() {
const { match } = this.props;
return (
<div className="advanced-configuration">
<div className="advanced-configuration__content userManagement__body">
<Link to={`${match.url}/test`}>Test</Link>
<Route exact path={`${match.url}/test`} component={() => <h1>test123</h1>} />
<Route exact path={match.url} component={() => <h2>Hi from main compoponent</h2>} />
</div>
</div>
);
}
}
The statement: "Hi from main component" Gets loaded as i arrive in this route, but as i click on the test link, it falls into my "404" route, which is:
<Route component={NotFound} />
This NotFound route is sibling of MyComponent, and it is in the end of the root switch, the first one that i posted on this question.
What else can i look into, to try to see what is breaking this link?
Have you tried using match.url. Something like this. Here is what documentation says about it.
const Topics = ({ match }) => (
<div>
<ul>
<li>
<Link to={`${match.url}/rendering`}>Rendering with React</Link>
</li>
<li>
<Link to={`${match.url}/components`}>Components</Link>
</li>
</ul>
<Route path={`${match.url}/:topicId`} component={Topic} />
<Route
exact
path={match.url}
render={() => <h3>Please select a topic.</h3>}
/>
</div>
);
const Topic = ({ match }) => (
<div>
<h3>{match.params.topicId}</h3>
</div>
);
Have you tried something like :
let match = this.props.match
<div>
<h1>Here Some Text</h1>
<Link to={match.url + '/test'}>Test</Link>
<Route exact path={match.url + "/test"} component={MyOtherComponent} />
</div>
In your updated question, I am able to see the rendered JSX by clicking on the link using this markup :
<Link to={match.url + '/test'}>Show Test!</Link>
<Route path={match.url + "/test"} component={() => <h1>test123</h1>} />
I'm trying to implement React Router v4 in my create-react-app app and my routes work except for the route with an /:id parameter as it just renders a blank page. I've searched for 2 days and tried implementing the solutions here which says to add <base href="/" /> to the head section of index.html and I've also tried following this Medium guide for simple routing but it still does not work. I don't understand, what is going on?
My code is below, any help is greatly appreciated!
Index.js
ReactDOM.render((
<BrowserRouter>
<App />
</BrowserRouter>),
document.getElementById('root'));
registerServiceWorker();
App.js
class App extends Component {
render() {
return (
<Routes />
)
}
}
Routes.js
export const Routes = () => {
return (
<main>
<Switch>
<Route exact path="/" component={Home} />
<Route exact path="/movies" component={Search} />
</Switch>
</main>
);
}
Search.js
render() {
let filteredMovies = this.state.movies.filter((movie) => {
return movie.title.toLowerCase().indexOf(this.state.search.toLowerCase()) !== -1;
})
return (
<div>
<p>Search Page</p>
<form>
<input type="text" value={this.state.search} onChange={this.updateSearch}/>
</form>
<div>
{filteredMovies.map((movie, idx) =>
<div>
<div key={idx}>
<Link to={`/movies/${movie.videoId}`}>
<img src={movie.image.high.url} height="160px" width="100px" alt=""/>
<p>{movie.title}</p>
<p>{movie.quality}</p>
</Link>
</div>
</div>
)}
</div>
<Switch>
<Route path="/movies/:id" component={Single} />
</Switch>
</div>
)
}
}
export default Search;
Single.js
class Single extends Component {
render() {
return (
<div>
<p>Single Movie...</p>
{this.props.match.params.id}
</div>
)
}
}
export default withRouter(Single);
Every route works except for /movies/:id where it just renders a completely blank page. It doesn't even show the <p>Single Movie...</p>.
You should remove exact from route that corresponds to Search component in your Routes, i. e.:
export const Routes = () => {
return (
<main>
<Switch>
<Route exact path="/" component={Home} />
<Route path="/movies" component={Search} />
</Switch>
</main>
);
}
The explanation is pretty simple: the exact prop means that your component will render only if current route is exactly the same as you specified in the path prop
Update
If you want to render the list of movies only when no :id is specified, you should render your list in Switch:
<Switch>
<Route exact path="/movies" render={props => {
return (
<div>
{filteredMovies.map((movie, idx) =>
<div>
<div key={idx}>
<Link to={`/movies/${movie.videoId}`}>
<img src={movie.image.high.url} height="160px" width="100px" alt=""/>
<p>{movie.title}</p>
<p>{movie.quality}</p>
</Link>
</div>
</div>
)}
</div>
)
} />
<Route path="/movies/:id" component={Single} />
</Switch>