I am trying to write a function that sets the current location to the route that was just clicked. However, as you can see, it gives me the url of the page I was on WHEN I clicked the button, not the page of path of the button itself. What should I use instead of window.location.pathname?
const setLocation = () => {
console.log(window.location.pathname);
setCurrentLocation(window.location.pathname);
};
<Link onClick={() => setLocation()} to="/today" className="btn btn-primary btn-sm">
<Link onClick={() => setLocation()} to="/upcoming" className="btn btn-primary btn-sm">
Why are you storing this to the state ?
ReactRouter has a hook useLocation https://v5.reactrouter.com/web/api/Hooks/uselocation in which you can take .pathname of any pushed path to history.
If you really want to store location by yourself pass on the route value in to as a param in setLocation function or create a component that wraps the Link component and does store location : )
ie:
<Link onClick={() => setLocation("/upcoming")} to="/upcoming" className="btn btn-primary btn-sm">
code is like ===>
onClick={
(e)=>console.log(e.target.href)
setLocation(e.target.href)
}
const setLocation = (path) => {
console.log(window.location.pathname);
setCurrentLocation(window.location.pathname+path);
};
Related
Is it possible to reload on click on a Link component from next/link? I tried to put my own function on the child div from the link that says to reload on click. But then it reloads before the route has changed and it didn't change route anymore.
const router = useRoute();
const hanldeRefresh = () => {
router.reload();
}
<Link href={title.slug}>
<button onClick={handleRefresh} class="button">{title.buttonText}</div>
</Link>
Instead of using Link, you can use router like this
const router = useRoute();
const handleClick = async (title) => {
// Wait for route change before do anything
await router.push(title);
// Reload after routing
router.reload();
}
//<Link href={title.slug}>
<button onClick={() => handleClick(title.slug)} class="button">
{title.buttonText}
</button>
//</Link>
I built this toy problem to replicate an issue I am facing in a larger app. Why does handleClick not fire when the button is clicked?
const Button = () => <button type="button">Click me</button>;
export const App = () => {
const handleClick = () => {
console.log("clicked");
};
return <Button onClick={handleClick} />;
};
You pass onClick={handleClick} as a property to Button but the Button component does not use the property.
const Button = () ... // ⚠️ no onClick property used
You can fix this by responding to the onClick property -
const Button = ({ onClick }) => // ✅
<button type="button" onClick={onClick}> // ✅
Click me
</button>
An obvious improvement would be to respond to the children property as well. This allows the caller of Button to write anything in place of the static Click me -
const Button = ({ onClick, children }) =>
<button type="button" onClick={onClick}>{children}</button>
<Button onClick={handleRegister}>Register</Button>
<Button onClick={handleLogin}>Login</Button>
<Button onClick={handleSave}>Save</Button>
Note children can be passed as a property. Sometimes you will see components use children in this way. Both examples function identically -
const Button = ({ onClick, children }) =>
<button
type="button"
onClick={onClick}
children={children}
/>
Another common thing for Button components like this is to automatically prevent the default event for the onClick handler. We can also accept a type property and set the default to "button" if the caller does not otherwise specify -
const Button = ({ type = "button", onClick, children, preventDefault = true }) =>
<button
type={type}
onClick={e => {
if (preventDefault) e.preventDefault()
onClick(e)
}}
children={children}
/>
<Button type="submit" onClick={handleRegister}>Register</Button>
<Button onClick={handleReset} preventDefault={false} children="Reset" />
In react I've used to push with history prop like this :
<button onClick={() => props.history.push('/someurl')} >
I tried this way but it doensn't work :
import { navigate } from '#reach/router';
<button onClick={ () => navigate(`/`);} > Navigate < / button>
Error :
Gatsby.js development 404 page
There's not a page yet at /
I've also tried this url :
navigate(`localhost:8000/`);
But it throws this error in the console :
Failed to launch 'localhost:8000/' because the scheme does not have a registered handler.
It says the page doesn't exist but it does and I've checked it by putting the same url in browser and it does exist .
How can I push something to url in gatsby ?
Instead of importing navigate from #reach/router, use the Gatsby-provided wrapper:
import { navigate } from "gatsby"
const HomeButton = () =>
<button onClick={() => navigate("/")}>
Homeward!
</button>
If you want to change the URL without keeping the previous page in history you can also pass the second argument an options object with replace set to a truthy value. E.g.:
const HomeButton = () =>
<button onClick={() => navigate("/", { replace: true })}>
Homeward!
</button>
I am working on gatsby. I need to go back to privious page/link as I used to do with reactjs.
<a onClick={() => this.props.history.goBack}>
<button type="button" className="close_tab">
<img src={Close} alt="" />
</button>
</a>
How can I do this using gatsby?
Use navigate(-1):
import React from "react";
import { navigate } from "gatsby";
export default function GoBack() {
return (
<Button onClick={() => navigate(-1)}>
Go Back
</Button>
);
}
Edit: Since reach-router#1.3.0, you can now simply call navigate(-1) to go back. Manually update reach-router in your Gatsby project if it's not yet updated. Thanks #nathan in the comment for the tip.
Edit: Ah alright, I've just realized this.props.history.goBack is a react-router thing. Gatsby doesn't use react-router, but reach-router under the hood and it doesn't have the history props or the goBack method. There's a issue requesting to add this, but wasn't implemented. You'd have to use browser's own history object as I suggested below.
import React from 'react'
const BackButton = React.forwardRef(
({ children, ...props }, ref) => {
const onClick = e => {
e.preventDefault()
history.back()
}
return (
<a {...props} ref={ref} href="#" onClick={onClick}>
{children}
</a>
)
}
)
BackButton.displayName = 'BackButton'
export { BackButton }
Is this.props.history the browser's history? If so, you can do this.props.history.go(-1) to go back to the previous page.
As always with Gatsby, watch out when you use methods from browser, since they don't exist during html generation:
export default () => (
<button onClick={() => {
typeof history !== 'undefined' && history.go(-1)
}}>back</button>
)
For a function component in Gatsby:
<a onClick={() => window.history.back()}>Go back</a>
The gatsby navigate function is type as NavigateFn.
Which you can find declare as:
export interface NavigateFn {
(to: string, options?: NavigateOptions<{}>): Promise<void>;
(to: number): Promise<void>;
}
So, as you can see, you either can pass the route you want to redirect to, or an specific number.
Try with navigate(-1)
This should work
import { navigate } from "#gatsbyjs/reach-router";
<button onClick={() => navigate(-1)}>Back to previous page</button>
It goes to the previous page
I have a React form which has the following form submission button:
<Link
className="btn btn-secondary btn-width-200 search-submit"
to={{pathname: '/booking/search', query: this.state.filters}}>
Search
</Link>
In the above link I want to call a function handleSubmit(evt) on button click.
handleSubmit(evt) {
evt.preventDefault();
this.setState({form_submitted: true});
}
<Link className="btn btn-secondary btn-width-200 search-submit" to={{pathname: '/booking/search', query: this.state.filters}} onClick={this.handleSubmit.bind(this)}>Search</Link>
But the following ignores the to={{pathname: '/booking/search', query: this.state.filters}} and just takes handleSubmit function into consideration
Is there anyway to add to={{pathname: '/booking/search', query: this.state.filters}} to the handleSubmit function? Or is there anyway to resolve this issue?
This 👇🏼 :
import {Link} from 'react-router';
handleSubmit(evt) {
evt.preventDefault();
this.setState({form_submitted: true});
}
<Link
className="btn btn-secondary btn-width-200 search-submit"
to={{pathname: '/booking/search', query: this.state.filters}}>
Search
</Link>
Can be replaced by 👇🏼 :
import {browserHistory} from 'react-router';
handleSubmit(evt) {
evt.preventDefault();
this.setState({form_submitted: true});
return this.redirect('/booking/search', this.state.filters);
}
redirect(to, query) {
browserHistory.push({pathname: to, query})
}
<a
className="btn btn-secondary btn-width-200 search-submit"
onClick={this.handleSubmit} >
Search
</a>
All you need to understand is, how to achieve route using react-router API. Basically you can configure it on two API, browserHistory and hashHistory. (link)
So, in otherword, by calling browserHistory.push('/booking/search') or hashHistory.push('/booking/search') you should be able to navigate between routes.
There is redux version also available, just in case if you want to manage your navigation via some action dispatch (though it is not necessary). Link
For more info: Programmatically navigate using react router
You can use the push router method in external Function instead of using Link. For example:
redirectFunction() {
this.handleSubmit()
router.push({
to: '/booking/search',
query: this.state.filters
})
}
render () {
<div
className="btn btn-secondary btn-width-200 search-submit"
onClick={this.redirectFunction.bind(this)}>
Search
</div>
}