Gatsby's `navigate` function to navigate to the same page? - reactjs

Is it possible to use Gatsby's navigate function to navigate to the same page?
For instance, I built a search component that lives on the navigation bar, therefor accessible on any page. Once users perform search, they get routed to the Search Results page via navigate(/search-results).
If they are on that page, and want to perform the search again, that navigate function does not work, hence no results display.
I'm aware I could do a window.location.reload() but wanted to see if there are other ways.

Gatsby's navigation (Link component or navigate function) doesn't support parameters per se as you want to.
From Gatsby's docs:
Neither <Link> nor navigate can be used for in-route navigation with a
hash or query parameter. If you need this behavior, you should either
use an anchor tag or import the #reach/router package—which Gatsby
already depends upon—to make use of its navigate function, like so:
So, that said, you have two approaches:
Importing the navigation from #reach/router:
import { navigate } from '#reach/router';
onClick = () => {
navigate('?foo=bar');
}
Using window.location as you pointed
Of course, the #reach/router will give you a smoother workaround.

Related

How add ability add query params for gatsby routes?

How to generate pages in gatsby that will allow you to add parameters to the routing like https://page1?someParam=param or https://page1/param
What I mean? When we navigate to page page1 in gatsby it work's fine, but what if I just want add uniq params for page for google analitics? so for this I want to have ability
add some additional params for the page from where I made redirect, but when I add
for page1 some params like https://page1?someParam=param or https://page1/param, it updated and show me just https://page1 instead.
I suppose that it's related to way how I created pages. Here is my code:
createPage({
path: `${localePrefix}/${slug}`, // so should I change it here in order to work as needed?
component: PageTemplate,
context: {
...context,
localizedPaths,
},
})
Can it be fixed with?
matchPath: path: ${localePrefix}/${slug}?*,
matchPath: path: ${localePrefix}/${slug}/*,
Recap:
My question is about why gatsby remove query params from pages?
https://some_site/some_page?some_param=323
translates into
https://some_site/some_page
https://page1?someParam=param or https://page1/param are not the same. While a query parameter (first case: ?someParam=param) is an optional value that doesn't change the rendered page (it doesn't point to any specific route hence it's not requesting any file). The second one (https://page1/param) is accessing a /pages/param route.
Since they are URL parameters, you don't need to change anything in your project, you just need to catch them using JavaScript. They are handled in thee:
const urlParams = new URLSearchParams(window?.location?.search);
Note: you can access directly location prop in Gatsby
If your project is replacing https://some_site/some_page?some_param=323 to https://some_site/some_page it's because some server-side configuration or a CDN, not because of Gatsby's behavior, like any other React project.

Pass onclick function to component using react router

I'm (obviously) fairly new to ReactJS. I'm using Router v6 for navigation between pages. I have a case where the action of a button on Component A must depend on which component (B or C or ...) launched the page. But, using useNavigate, it doesn't seem to be possible to send a function to the target component A, only text fields seem to be allowed in the object. That is, the following doesn't work:
let navigate = useNavigate()
function nextClick() {
navigate('/UserProfile', {state:{
okClick: userProfileOkClick,
cancelClick: backButtonClick
}})
}
That is, I want to navigate to the UserProfile component, and pass the callback functions its buttons should use. It doesn't work -- in the UserProfile page, the state object is null.
So is there a way to navigate to a new page and dynamically change the button callbacks? I hope so...
Thanks!

React web navigation based on anchors

I'm trying to setup a single page react web application. My application only has one page with all the components places one after the other, so, the common react-router solution that lets you render only some part of the application doesn't work for me.
The intention is to have only one page (as large as it becomes) and the user can navigate between sections on it through a menu (or similar). Also, the site should recognize when someone types the URL like http://url.com/#section4, and scroll automatically to the requested section, marking the selected section on the menu as active.
Also, like a nice to have, it would be awesome if the URL can change depending on page scroll.
How can I achieve this?
I found this library that works in conjunction with the React Router's BrowserRouter, and allows to have a based anchor navigation, and also customize the scroll function were you can put offset or anything you wan to. Something like this:
<NavHashLink to="#anchor1" scroll={el => this.scroll(el)}>Anchor1</NavHashLink>
scroll (el) {
const offset = document.getElementById('element').offsetHeight
window.scrollTo({ top: el.offsetTop - offset, left: 0, behavior: 'smooth' })
}
You should either use HashRouter from react-router-dom package, or you can use a NavLink from the same package like this:
<NavLink>
to="/foo/#bar"
isActive={()=> window.location.pathname + window.location.hash === "/foo/#bar"}
</NavLink>

See list of history through react-router props

I currently have a button that onClicks to history.goBack but I want it to direct the user to another path if there isn't a previous page (in the case the user visits the page directly by typing in the URL in the URL bar instead of clicking within the site to get there). When I checked out this.props.history there isn't an object containing the history of pages visited or a boolean that tells me if there is a page for history.goBack to work on. How do I check that? Looking at the docs for history library, there is suppose to be an entries property but this somehow didn't make it into react-router.
You can use go() property to move further back.
Eg. go(-1) will be equivalent of goBack() and go(1) will be equivalent of goForward().
I don't think there is a way to list all the paths on the stack, but you could allways implement history that you can push to and control.

Using react-router-redux can Link components be used to transition after loading a routes state

I have been using react-router-redux which allows for my location to be stored in state nicely, and allows me to use react-router for defining routes, and linking between routes.
One problem seems to be that when I need to navigate using a <Link /> component like so:
<Link to={`/movie/${m.id}`}>
<p>{m.name}</p>
</Link>
this will trigger the change of route, and on load of the new route, in this case the <Movie /> route, the state for the movie page is loaded.
This doesn't really work nicely for transition between pages, as the new page will be blank on navigation, or you can put in a loader but really it should not navigate to the new page until the api call for the new page has loaded. Similar to sites like pitchfork.com or theguardian.com
This implementation has been discussed in this question and the approach of just using a loader between page transitions is used in the real-world-example and reddit api example
My question is, if I want to load state for the new container/route in my site before navigating, do I need to follow the approach suggested by dax chen in this question?
To sum up the answer was to fire an action and using redux-thunk we can preload the state by calling the action for the new container/route, then on completion we navigate to the page using react-router-redux's push() action
store.dispatch(push('/foo'))
If this is the recommended approach for preloading a page before transition, then I will be changing my react-router-redux-example and my current site to use this approach.
An action to load the new route's data then navigate will look something like this:
function fetchInit(url, id, to) {
return dispatch => {
return dispatch(fetchMovie(url, id))
.then(function(home) {
return dispatch(push(to))
})
}
}
It will need some logic to identify the new container's action to call and also the new path to navigate to. It may call the static fetchData() method on the new page's container component.
So this will somewhat complicate the <Link /> component, I am just looking for some advice on if this is the correct way, or I may have missed a simpler more recommended approach.
<Link onClick={ () => dispatch(navigate(`/movie/${m.id}`, 'Movie')) } >
<p>{m.name}</p>
</Link>
I made an implementation that solves this, and it is possible to make any type of custom link component and have it act in any way you like, however it is probably not a good idea for it to wait for a long load event before changing to a route, as users want the route transition to be immediate. The better approach is to use a nice loader and mix it in to the design of your page well, similar to what is done on pitchfork.com and also to ensure data comes back from the API quickly using caching e.g. redis, memcached.
Here is the library I made showing a custom react-router-redux link component: https://github.com/StevenIseki/react-router-redux-link

Resources