I am using React Router.
I want when the user clicks on the button, it directs them to the page (endpoint) /form which has the UserForm component.
Here is my code wrapping the button:
<Router>
<Link to="/form" className="updateLink">
<button className="updateBtn" onClick={() => {
this.update(id);
console.log(`Item Number: ${id} Was Updated Successfully`);
window.alert(`Item Number: ${id} Was Updated Successfully`);
}}>U</button>
</Link>
<Switch>
<Router exact path="/form" component={UserForm} />
</Switch>
</Router>
So the reason that doesn't work is because the Button has its own click handler separate from the link handler. You have two options available to you:
Style the Link tag such that it looks like a button but don't actually look like a button (this won't work if you need to do additional logic in addition to routing)
Actually use a button. And then use the 'useHistory' React Hook React Router provides to get the functionality you're looking for.
The component would look something like this:
const history = useHistory()
return (
<Button onClick={() => history.push("/abc")}/>
)
I would personally recommend that you simply style the link tag in the way that you need it to. As that would be more accessible and understandable to the user. But that's only a good idea if you only care about the routing.
Is the above code accurate as in your code?
Router statement should be set up as below, usually in App.js
<Router>
<Switch>
<Route path = './form' component = {form}
</Switch>
</Router>
You then create the form component and to link to it you then import the link component in the component you wish to use it.
Then use as below
<Link to = './form'> Some Text </Link>
Onto the button issue you are having
It will render but you shouldn't nest an <a> or <button> tag in HTML as it wont be sematic for screenreaders, isn't accessible, nor it it valid HTML.
The Link element in react creates and renders an <a> tag which shouldn't be nested in a button.
You could use useHistory in your case for the same effect
import React from 'react'
import { useHistory } from 'react-router-dom'
const component = () => {
const { push } = useHistory()
...
<button
type="button"
onClick={() => push('/form')}>
Click me to go to a form!
</button>
...
}
Related
I have a "login" screen (entering name only) with the button - without nav links. I want to make an additional screen with different content when the button is clicked, but I can't figure out how to do it.
React version: 18
I tried to add a router, but I didn't know how to set it against the components (I have no links or additional url).
To create a new screen in a React application, you can use a router and add routes for each of the screens in your app.
Install the react-router-dom package, which provides the components and functions you need to use routing in React.
npm install react-router-dom
Import the BrowserRouter, Route, and Link components from the react-router-dom package in your app's entry point (e.g. index.js):
import { BrowserRouter, Route, Link } from 'react-router-dom';
Wrap your app's root component with the BrowserRouter component to enable routing:
ReactDOM.render(
<BrowserRouter>
<App />
</BrowserRouter>,
document.getElementById('root')
);
Add a Route component for each screen in your app, specifying the path for the screen and the component that represents the screen. For example, to add a "Profile" screen, you could do the following:
function App() {
return (
<div>
{/* Other components and content here... */}
<Route path="/profile" component={Profile} />
</div>
);
}
Now add an onClick event on your button e.g
<button type="submit" onClick={onClick}>
Go to Profile
</button>
and this is how you can use:
function LoginForm() {
....
const navigate = useNavigate();
const onClick = () => navigate('/profile');
....
....
}
I am new to javascript and react, and i am trying to route from one component to another when a button is clicked.
example of html code in the sign up page:
<!-- signup button -->
<div id = "signup">
<button class="signupbutton">Sign up</button>
</div>
so when the sign up button i want it to route to this html page:
<!-- page title -->
<h1><strong>Let's get started! First up, where are you in the planning process?</strong</h1>
Any ideas on how i can do this? - i know i need to do this in javascript and with react (i ahve created a JS file for the sign up page and planning process page), but i am a bit unsure of how to do so. Any ideas?
You can't link in HTML directly with React. You need to set up two components first.
One for the page with the Button:
export default function ButtonPage () {
return (
<div id = "signup">
<button className="signupbutton">Sign up</button>
</div>
);
}
One with the page for the Get Started Page:
export default function GetStarted () {
return (
<h1><strong>Let's get started! First up, where are you in the planning process?</strong</h1>
);
}
Then You need to set up your main component, the App component and link the child components you want to display. If you use the latest version of React you need to import BrowserRouter, Route and Routes from react-router-dom:
import { BrowserRouter, Route, Routes } from "react-router-dom";
export default function App () {
return (
<BrowserRouter>
<Routes>
<Route path="/signup" element={<ButtonPage/>}></Route>
<Route path="/getstarted" element={<GetStarted/>}></Route>
</Routes>
</BrowserRouter>
);
}
Then you need to import Link from react-router-dom inside your ButtonPage Component and Link to the other Component:
import { Link } from "react-router-dom";
export default function ButtonPage () {
return (
<div id = "signup">
<Link to="/getstarted">
<button className="signupbutton">Sign up</button>
</Link>
</div>
);
}
Et voilĂ : You linked two pages in React. For more information, look up the documentation of React-Router here.
I have 3 components in nextjs and i want to achieve the below snippet in nextjs
<Route path="/" component={homePage} />
<Route path="/about" component={aboutPage} />
<Route path="/faq" component={faqPage} />
Q1. How can i do the same in nextjs without page refresh? (without react-router)
(Edit : some scholars are suggesting to read the docs but i have read it thoroughly and what i want is to pass a component along with the route)
Is this even possible in next js?
Q2: If i have url as /products?product_id=productid and on refresh if i want the url to be /products (basically i want to remove all params on refresh) What is the best practice to do this?
Thanks in advance
NextJS functions on a convention-based filesystem-based routing. You'd need to place your components in a directory structure that matches the routes you are wanting.
More details here:
https://nextjs.org/docs/routing/introduction
The Next.js docs don't really cover how to change away from <Route> components, however they have a lot of examples as code on how to do most things with Next.js. https://github.com/vercel/next.js/tree/canary/examples/layout-component
The below is what I used as an alternative to the component (there's no direct Next.js alternative).
_app.js
export default function MyApp({ Component, pageProps }) {
// Use the layout defined at the page level, if available
const getLayout = Component.getLayout || ((page) => page)
return getLayout(<Component {...pageProps} />)
}
Any page:
import Layout from '../components/layout'
import Sidebar from '../components/sidebar'
export default function About() {
return (
<section>
<h2>Layout Example (About)</h2>
<p>
This example adds a property <code>getLayout</code> to your page,
allowing you to return a React component for the layout. This allows you
to define the layout on a per-page basis. Since we're returning a
function, we can have complex nested layouts if desired.
</p>
<p>
When navigating between pages, we want to persist page state (input
values, scroll position, etc) for a Single-Page Application (SPA)
experience.
</p>
<p>
This layout pattern will allow for state persistence because the React
component tree is persisted between page transitions. To preserve state,
we need to prevent the React component tree from being discarded between
page transitions.
</p>
<h3>Try It Out</h3>
<p>
To visualize this, try tying in the search input in the{' '}
<code>Sidebar</code> and then changing routes. You'll notice the input
state is persisted.
</p>
</section>
)
}
About.getLayout = function getLayout(page) {
return (
<Layout>
<Sidebar />
{page}
</Layout>
)
}
The main part for the layout that you want to wrap around the pages, components/layout.js:
import Head from 'next/head'
import styles from './layout.module.css'
export default function Layout({ children }) {
return (
<>
<Head>
<title>Layouts Example</title>
</Head>
<main className={styles.main}>{children}</main>
</>
)
}
What's happening is the _app.js wraps all pages inside the declared layout. Each page then defines what layout that page belongs to. The layout then accepts a page as the {children} prop object of which you can then render anywhere in your layout page.
Next uses filesystem based routing, your folder structure should look like
-- pages
-- index.js
-- about/index.js
-- faq/index.js
For the custom component part, make a component that's clickable, on click, use next builtin router to redirect
const router = useRouter();
router.push('/');
I am currently in process of making a website, and hit a wall on this. I am using react-router-dom for routing my app, and kinda new to it, but in one page, the link that I put on the page does not change the URL
I already tried on previous component, in which I put the button on one component, then use the Link to load another component based on the Link and Route given. However, on this one, despite using similar structure as before, does not work at all
This is the code for the page that loads. I already imported the BrowserRouter as Link from react-router-dom
<div>
<p>TEST</p>
<Link to="/leadslist"><button class="btn btn-success">Back to Leads List</button></Link>
</div>
This is the target page
<div>
<Router>
<Switch>
<Redirect from="/leads" to="/leadslist" />
<Route path="/leadsForm" component={LeadsForm} />
<Route path="/leadslist" component={LeadsList} />
<Route path="/leaddetails" component={LeadsDetails}/>
</Switch>
</Router>
</div>
my previous try clicking button from "/leadslist" to "/leadsForm" actually worked, but then I try to load to "leaddetails" to try to go back to "/leadslist", but it doesn't change the URL at all. Any help will be truly appreciated.
You should not be importing BrowserRoute as Link from the react-router-dom. Both are different things. You need to import Link directly from react-router-dom. Rest, it should work solid.
You should be importing link this way:
import { Link } from "react-router-dom";
Now, I am not sure what's exactly happening your app. But here, I have created a very basic demo or working react-router using CodeSandBox. You can take a look, it should help you fix the problem you are having.
Also, you can read this article to further understand the working of the react router.
Your code doesn't work because you have added button inside Link tag so on click of button React only fires onClick method of button and Link will no be clicked!
So in solution, you can remove a button from Link tag
<Link to="/leadslist">Back to Leads List</Link>
or You can use Below solution,
Instead of adding button in Link You should do this,
import withRouter from 'react-router-dom'
const Component = (props) => {
<div>
<Button onClick={()=>props.history.push('/leadslist')}
</div>
}
export default withRouter(Component)
Add HOC withRouter to your component and you can get history object in prop.
I have set up a basic react app with hash navigation. Problem is when I click on any link to navigate between pages, I see that the hash in the url is changing properly, as well as I added a console.log in my layour's render to see if it's getting called and it is, with proper this.props.children values, however the page is not rendering anything. If I go to any route and refresh the page I see the correct components rendered, but if I navigate somewhere from there noting gets rendered until I refresh again.
import React from "react";
import ReactDOM from "react-dom";
import { IndexRoute, Router, Route, Link, hashHistory as history } from 'react-router';
class Layout extends React.Component {
render() {
console.log(this.props, document.location.hash);
return <div>
<div>
<span>LEYAUTI MLEAYTI {Math.random()}</span>
</div>
<div>
{this.props.children}
</div>
<div>
{this.props.params.project}
</div>
</div>
}
}
class CreateProject extends React.Component {
render() {
return <div>
<h1>Create PROEKT</h1>
</div>
}
}
class Projects extends React.Component {
render() {
return <div>
<h1>PROEKTI MROEKTI</h1>
<Link to="/projects/create">New project</Link>
</div>
}
}
ReactDOM.render(
<Router history={history}>
<Route path="/" component={Layout}>
<IndexRoute component={Projects}/>
<Route path="projects/create" component={CreateProject}/>
</Route>
</Router>,
document.getElementById('app-root'));
Here is a visual of what's happening in the console when I navigate on a couple routes, but the DOM remains unchanged
This may be an issue with hashHistory. Which react-router version are you using? With v4 and above, you need to use history like so -
import createHistory from 'history/createHashHistory'
const history = createHistory()
// pass history to the Router....
Your component didn't actually unmount/remount if you only update your hashtag in your url. The route however, is updated. So you can only see the component loads content for once when you refresh the page.
You will need to create state variables and update it in a routeChange handler callback and bind the updated state variable to your view by using setState. Then the component can get updated.
See this post for how to add the route change listener (https://github.com/ReactTraining/react-router/issues/3554)
Alright, so I got down to the bottom of it.
The problem was that I was including my client.min.js file before the default app.js file of laravel 5.4's default layout. For some reason it broke react in a very weird way. What I had to do is switch the order in which the two files were included.