Routing to specific part of other component in React - javascript

I have a problem with routing to a specific part of another functional component in React.
I have declared Route in Main component and Link around the place where I want to redirect from... it looks like this...
The main function gets:
<Switch>
<Route exact path='/news/:eyof' component={News} />
<Route exact path='/news/:svetsko' component={News} />
<Route exact path='/news' component={News} />
</Switch>
And I defined in other functional component:
<div className="card">
<Link to="/news/:svetsko">
<div className="card-header">
<h3>Artistic gymnastics world championship</h3>
</div>
</Link>
</div>
So by clicking on this link, I need to get redirected to News page class "svetsko" so I can read about that news... All news are in containers in same page....

Try something like this in your component:
let { scrollToSection } = useParams();
svetskoRef = React.createRef();
useParams() allows you to access :svetsko. When the component loads, you can use scrollToSection to navigate between different parts of the page. The scrollRef is used to access the DOM element you want to scroll to.
window.scrollTo(0,scrollRef.offsetTop)
The markup would look something like this:
<div className="card" ref="svetskoRef">
<Link to="/news/:svetsko">
<div className="card-header">
<h3>Artistic gymnastics world championship</h3>
</div>
</Link>
</div>

You need only one route like
<Switch>
<Route exact path='/news' component={News} />
</Switch>
you can give link like
<Link to={{
pathname: '/news',
state: { news : yourNewsName } // you can pass svetsko here
}}>
<div className="card-header">
<h3>Artistic gymnastics world championship</h3>
</div>
</Link>
You can access this state in your News Page like
<div>{ props.location.state !== undefined ? props.location.state.news : '' }</div>
After getting your news type like eyof :
Step 1 :
you can create on functional component which takes argument as your
data and return your new post jsx with your data.
Step2 :
So,when you get your eyof in your page then you are going to call
this function and pass your data related to your eyof and that function
return your new post to your page.

Ok, I found one really good library as a solution, it's called react-scroll and it has an option to wrap link you need in earlier defined scroll link, and to wrap component you want it to link as a specific part of the page with Element with id you gave to scroll link as a parameter... Try it if you need it somehow.

Related

How to load a component from a button click in react?

I'm creating a simple react app. I need to load a component from a button click. When I click the edit button I need to load the edit component. I tried it using <Link>. But I can't understand how to give the relative path. It means it need to load it like http://localhost:3002/viewTicket/603c9a02a2ccd501f45f820e/edit. I need to load it from http://localhost:3002/viewTicket/603c9a02a2ccd501f45f820e. How can I give the relative path?
App.js
<Provider store={configureStore()}>
<BrowserRouter>
<div className="App">
<LayoutWrapper>
<Switch>
<Route path="/" exact component={Home} />
<Route path="/viewTicket/:id" exact component={ViewTicket} />
<Route path="/viewTicket/:id/edit" exact component={EditTicket} />
</Switch>
</LayoutWrapper>
</div>
</BrowserRouter>
</Provider>
Ticket.js
<Link to="/viewTicket/:id/edit">
<Button size="lg" onClick={this.handleEdit}>
<Pencil />
Edit
</Button>
</Link>
But url lokks like this.
Is there any other way to do this?
You forgot to include the actual ID in the URL. You're just directing the user to this literal string that has ":id" in it:
<Link to="/viewTicket/:id/edit">
Whatever your ID values is (for demonstration let's assume it's in a variable called id), you'd use that to build your URL:
<Link to={`/viewTicket/${id}/edit`}>
As an aside, this is a very strange structure and will likely lead to confusion:
<Link to="/viewTicket/:id/edit">
<Button size="lg" onClick={this.handleEdit}>
Putting a button inside of a link means that you're trying to simultaneously do two different things. Should this.handleEdit be invoked? Or should the user be redirected by the link? It's best to invoke a single operation. If some logic needs to happen inside of this.handleEdit before redirecting the user, then remove the <Link> and manually redirect the user (likely using the useHistory hook) after performing that logic.

react routing two cmponents

very new to react router. i know this code isn't written the cleanest but how come when i click the button (Link to='/question') it renders
and BUT also renders the button still. i tried
setting it into a new route but unfortunately still doesn't work.
also is this how you would structure a basic router that needs to
render two separate components? i see i can do render={} or component={}
but not really sure how to render more than one component with one
router---- wit those two questions considered i basically just want
this button to render a new page ('/question') that has two components on it--- AFIB and QFIB and nothing else (right now its rendering the button and the two new components in addition... here is the code:
<div class='qAndAContainer'>
<Router>
<Link to='/question'><button className="px-4 nextQuestion startButton py-2 bg-pink-600 text-white text-sm uppercase font-medium rounded hover:bg-pink-500 focus:outline-none" >Begin
</button>
</Link>
<Route path='/question' component={(props) => (
<QFIB {...props} />
)} />
<Route path='/question' component={(props) => (
<AFIB {...props} />
)} />
</Router>
</div>
)
}
export default StartTest
React Router's Route component is basically a glorified string-match for your browser's URL.
In this case, what you're presenting to React Router is three Routes with the same strings to match, so it shows them all!
This is actually useful, for example rendering the same navigation bar for /dashboard AND /dashboard/messages.
But in your case, you just want one route or the other. So for React Router to understand you just want one of many, you need to wrap your Routes with a Switch component. React Router will only render the first match it finds, from top to bottom. Try to order your Routes in a Switch from most specific (longest paths) to least to get the best results.
I don't really care for the render or children props of Route (although they have their purposes), I usually prefer composing just like normal components.
<Router>
<Switch>
// this will actually match /question123/asdf/kdkd?foo=bar as well...
<Route path="/question">
<QFIB />
<AFIB />
</Route>
// `exact` tells the Route is must be... exact
<Route path="/" exact>
<Link to="/question">Go to Questions</Link>
</Route>
</Switch>
</Router>

Passing props down in Svelte

I'm trying to implement a fairly standard blog app using Svelte, Svelte Routing and Firestore, but I think I'm misunderstanding a fundamental part of how props are passed between components.
I based my initial code on the excellent tutorial on Fireship.io - which worked as per the tutorial: https://fireship.io/lessons/svelte-v3-overview-firebase/
From there I've added Svelte Routing - https://github.com/EmilTholin/svelte-routing - and I'm attempting to add a view route.
Relevant part of App.svelte:
<Router url="{url}">
<Navbar user="{user}" />
<div>
<Route path="posts/:id" component="{Post}" />
<Route path="posts/add" component="{PostForm}" />
<Route path="posts" component="{Blog}" />
<Route path="/" component="{Home}" />
</div>
</Router>
In my Blog Component I use a component called PostTeaser, in which I pass a link to the post view page.
Blog Component:
<div class="posts">
{#each posts as post}
<PostTeaser post="{post}" />
{/each}
</div>
PostTeaser component:
<div class="post-teaser">
<h2 class="title is-3"><Link to="posts/{ post.id }" {post}>{ post.title }</Link></h2>
<div class="post-teaser-content">{ post.content }</div>
</div>
Here I get a warning in the browser:
<Link> was created with unknown prop 'post'
Although the teaser does appear on the screen with the correct information.
When I click through to the post, i.e. the Post Component, my data is undefined.
I am placing export let post; in the script tag of each of my components.
Should I be using a "store" for my data? At the moment I'm fetching my data in the BlogComponent and passing it down the line. It would seem that this is incorrect. Any help gratefully appreciated.
See here for fuller example: https://codesandbox.io/s/romantic-cannon-ri8lo
With svelte-routing, you don't pass props from the <Link> component, you pass them from the <Route> component implicitly. Where you have this...
<Route path="posts/:id" component="{Post}" />
...you're telling the router that if the URL matches the pattern /posts/:id, it should render the Post component, passing it an id prop that matches that part of the URL.
The Post component is responsible for fetching its data based on that. So in this case, you could move the posts array into a separate module, and change Post.svelte accordingly:
<script>
import posts from "./posts.js";
export let id;
$: post = posts.find(p => p.id == id);
</script>
<div class="post">
<h1>{ post.title }</h1>
<div class="post-content">{ post.content }</div>
</div>
(Note that props are stringified because they're derived from the href, so we need a == comparison rather than ===.)
Here's a working fork.
Simple example:
Parent Component
<script>
import PostTeaser from "./PostTeaser.svelte";
let post = {
first: 'First prop',
second: 'Second prop'
};
</script>
<PostTeaser {...post} />
Child Component
<script>
export let first;
export let second;
</script>
First prop: {first} <br>
Second prop: {second}
Code here: https://codesandbox.io/s/spread-props-using-svelte-y7xou

React Router Link dont updated page data

I have this react + redux app
I have 1 Movie component with some movie data displayed on it which are fetched from API.
So at the bottom, i decided to add a Similar movies section with a couple of components to navigate to the new movie pages.
<div className="similar_movieS_container">
{ this.props.thisMovieIdDataSIMILAR.slice(0,4).map((movie,index)=>{
return(
<Link to={"/movie/"+movie.id} key={index}>
<div className="similar_movie_container">
<div className="similar_movie_img_holder">
<img src={"http://image.tmdb.org/t/p/w185/"+movie.poster_path} className="similar_movie_img" alt=""/>
</div>
</div>
</Link>
)
})
}
</div>
Now when I'm at a root route for instance /toprated and i click on a <Link to={"/movie/"+movie.id} key={index}> i get navigated to the particular route (e.g. /movie/234525 ) and everything works fine , but if I'm in a /movies/{some move ID } route and i click on some <Link to={"/movie/"+movie.id} key={index}> The route in the URL bar gets updated, but the page stays still, meaning nothing changes if I reload the page with the new route the new movieID data is displayed...
So how can i make a navigation to a new /movie/{movieID} FOMR a /movie/{movieID} ?
It's because you are just within same route.
There are few ways to work around this. I bet you are rendering routes like this.
<Route path="/movie/:id" component={Movie} />
Try like this.
<Route path="/movie/:id" component={() => <Movie />} />
Another solution would be to use componentWillReceiveProps instead of componentWillMount.
This happens because the component of page movie was mounted, so the render method of this component will not be mounted again or updated, so you need to fire a code to change the state, and consequently re-rendering the page content, for this you can implement the componentDidUpdate method which is fired for every props modification.
https://reactjs.org/docs/react-component.html#componentdidupdate
Basically you implement the same code above inside

React-router activeClassName not working as expected

For some reason, when I load/refresh the page in my app, the correct link is shown as active. When I click on a different link, it works as expected and becomes active, however the original link is also showing up as active.
UPDATE: I've just realised that when I click anywhere outside the menu bar, the active link loses its active status aswell, but the original link remains active. Essentially, when I click elsewhere, the menu returns to the example given in the first screenshot, even though the route URL is different.
Perhaps easier to demonstrate with screenshots:
This is shown on page load/refresh - as expected
But click on another link, and both of them now show as active
Click on another one, and the active link changes, but the original one is still showing as active as well
Here's my code:
One of the link elements (they are all identical, apart from SVG code and labels):
const AnnouncementLink = (props) => {
return(
<Link to="/announcements"
className={styles.assignmentLinkHolder}
activeClassName={styles.activeLinkHolder}
onClick={()=>props.hideSlideOver()}>
<span className={styles.iconHolder}>
<svg>
//Lots of SVG code here!
</svg>
<span className={styles.label}>
Announcements
</span>
</span>
</Link>
)
}
The menu element in full (not including some of the variable declarations which aren't relevant):
const photo = require('../../images/profilePics/blankface.jpg');
const SideMenu = (props) => {
//VARIABLE DECLARATIONS...
return (
<div className={styles.sideMenu}>
<img src={photo} className={styles.profilePic} />
<div className={styles.menuItem}>
<DashboardLink hideSlideOver={props.hideSlideOver} />
<CoursesLink hideSlideOver={props.hideSlideOver} />
<AssignmentsLink hideSlideOver={props.hideSlideOver}
badge={totalAssignments} />
<UsersLink hideSlideOver={props.hideSlideOver} />
<AnnouncementsLink hideSlideOver={props.hideSlideOver} />
<ReportsLink hideSlideOver={props.hideSlideOver} />
<DiscussionsLink hideSlideOver={props.hideSlideOver} />
</div>
</div>
)
}
And the React-router parent:
const Admin = () => {
return (
<Provider store={createStoreWithMiddleware(rootReducer)}>
<Router history={browserHistory}>
<Route path="/" component={Academy}>
<IndexRedirect to="/dashboard" />
<Route path="/dashboard" component={Dashboard} />
<Route path="/courses" component={CoursesMenu} />
<Route path="/assignments" component={AssignmentsMenu} />
<Route path="/users" component={UsersMenu} />
<Route path="/announcements" component={AnnouncementsMenu} />
</Route>
</Router>
</Provider>
)
}
OK, seem to have resolved it - not sure if this is a proper solution or just a workaround, but it seems to have done the trick.
The answer lies in the <SideMenu> component. By giving it a prop of path and linking this to the changing URL, it rerenders the component each time the URL changes. Also by removing <IndexRedirect> as suggested by oklas and changing it to <Route to='/'>, it prevents the active class from sticking on the <DashBoard> link.
Here's the code - this is from a section of the app that wasn't referenced above - the parent of <SideMenu>
<div className={styles.container}>
<SideMenu path={this.props.children.props.route.path} /> { //This 'path' property solves the problem by rerendering the SideMenu component every time the path changes }
<ViewPort>
{this.props.children}
</ViewPort>
</div>

Categories

Resources