How to change page title in navigation bar - reactjs

I want to change the text in my navigation bar depending on the content.
In my App.jsx file I have my routes as well as the navigation bar. Following a route should change it's text accordingly.
The quick and dirty solution of just copying the navbar into every component would definitely work, but I'm sure there are other ways.

As Mr. A said, you can have your Navbar component query for current page that is opened, via useLocation or useParams, and conditionally show different information.
This can be achieved by having an array of objects where you store given text for given page, such as
NAVBAR_TEXTS = [{page:"/", text: "Main page"}, {page:"/info", text: "Info page"}]
etc.
Then the text in the navbar would be
const location = useLocation();
const textToShow = NAVBAR_TEXTS.find(el => el.page === location.pathname)?.text

Related

How do I replace queries in the URL when on the same path? | Without useHistory() if possible

I have a page that displays products returned from my API based on the URL's search parameters. For example, '/products?search=socks' would return products with the word socks in the title. The search bar is located in the header. If I search for a product on the home page (a different path: '/'), it navigates to the product list page and displays the products. However, if I search for a product on the product list page (the same path: '/products'), it re-renders and removes the search parameters, leading to no products being displayed. I prefer to use current hooks as it appears useHistory is outdated.
I have tried to navigate to the URL directly:
navigate(`/products?search=${search}`);
And I have tried to set the parameters as one source suggested:
const params = new URLSearchParams();
params.set('search', search);
navigate(`/products?search=${search}`);
I expected the query/search parameter to replace the search value and re-render with the new results.
I would use the new React Router V6 useSearchParams hook:
import { useSearchParams } from 'react-router-dom'
Then instantiate the hook at the top of your component:
let [searchParams, setSearchParams] = useSearchParams();
Then you can manipulate the search params anywhere, in your case:
setSearchParams({ search: '...' );
Doing this along-side the navigate() call will basicallly lead the user to the page as the search param is being changed.
In your situation, I would detect if the user is already on the product list page before always running navigate(). You can use the useLocation() hook to detect what pathname you currently are on.
If you're on the product list page already, don't run navigate(). Your useEffect would be responsible for re-rendering the page when search params change using a dependency array [searchParams.search]:
useEffect(() => {
// do stuff when search params "search" variable changes
}, [searchParams.search])

From Navbar redirect to a certain part in a different page React

I want to redirect my users when they click on "How it works" button in the nabber, be redirected to the middle part of the home page, not from the top. Now when I do it I get redirected to the page as normal. I tried chakra ui (skip nav) but it isn't working. Any suggestions on how it could be done? package? right now I just have a normal useNavigate().
Using react-router-hash-link, you can make your navbar button to be a HashLink like so:
import { HashLink } from 'react-router-hash-link';
...
<HashLink to={'/your/home/path#location'}>How it works</HashLink>
Then, on your home page, let's say that the part you want to scroll to is wrapped in a div, we can start the page on that div by giving it an id of "location" like so:
<div id="location"></div>
Add id attribute to your middle section and try using useNavigate like this
const navigate = useNavigate();
navigate("/#YourMiddleSectionIdHere") //assuming you have to navigate to the middle section in your home page

How to setup React Router <Link> inside a Datatables.net Cell?

I have a datatables table (https://datatables.net) initialized like this:
$('#example').DataTable({
data: data,
columns: [{
title: "Database ID",
data: 'database_id',
render: function (data, type, row) {
return '<NavLink to="/shop">'+ data +'</NavLink>';
}
}]
});
The NavLink that i have in the code is supposed to render a database cell as a clickable link because of React-Router (This whole function is inside a React component), but the link is not rendering when i run the code.
What i ultimately want is the ability to click on a database cell that will take me to another component by routing into a link like "/shop/id" but i am stuck in it for a long time. Help!
I was facing the same issue and below solution is working for me.
You can directly add anchor tag with href to the path where you want to route upon on the click. But, it will reload your application.
To avoid reloading of the application, try below solution.
When you're initializing the columns dynamically, you can add below code for the column where you want to have a link.
fnCreatedCell: (nTd, data) => ReactDOM.render(
<a
onClick={() => handletableclick(data, props)}>
{data}
</a>, nTd)
Add handletableclick() function/method in your file to handle click event and programmatically through history push the path where you want to route upon the click
function handletableclick(data, props) {
props.history.push("/pathToRoute=" + data);
}
Also,in above code to access history from props, you will need to enclose your component with withRouter
like below :
export default withRouter(YourComponentName);

React navigation different route params on same route

I have a route in my app that can be navigated to from two different locations.
Specifically:
Home screen (StackNavigation) -> target route
Tab navigation -> target route
I have noticed that react navigation re-uses the same target route component (does not re-mount) regardless of which way the target route is navigated too.
Unfortunately, this means that route params are always the same as the first method used to navigate to the target route.
I would like to focus an input search box when the target route is navigated to from the home screen, but not when navigated via tab navigation.
Initially I was using this code:
useEffect(() => {
const _focusSearchBar = (payload) => {
if (props.navigation.getParam('shouldFocus') && searchBar && searchBar.current) {
searchBar.current.focus();
}
}
let focusSub = props.navigation.addListener('didFocus', _focusSearchBar);
_focusSearchBar();
return () => focusSub.remove();
}, []);
How can I achieve this? Also the target route loads data, so it is probably a good thing that it doesn't remount...
In essence I need a way of determining how the route was navigated too, through the home screen or via tab navigation.
Thanks!
Read https://reactnavigation.org/docs/en/navigating.html#navigate-to-a-route-multiple-times
you need to use navigation.push() to run copies of your component with different params.

Handle back button with react router

If a user navigates to www.example.com/one and clicks the back button, I want to redirect them to www.example.com.
I think it's a common problem, but I haven't found a solution yet.
Hooks version (React 16.8+):
Minimal version.
import { useHistory } from "react-router-dom";
export const Item = () => {
let history = useHistory();
return (
<>
<button onClick={() => history.goBack()}>Back</button>
</>
);
};
In react-router-dom v6 useHistory() is replaced by useNavigate(). so use useNavigate() inplace of useHistory() this way.
import { useNavigate} from "react-router-dom";
export const Item = () => {
let navigate = useNavigate();
return (
<>
<button onClick={() => navigate(-1)}>Back</button>
</>
);
};
for more on useNavigate visit this: https://reactrouter.com/docs/en/v6/hooks/use-navigate
You can try with two options, either you can use push method or goBack method from history of the router. Normally history props will available if you directly route the component via Route method or pass the history props to child component and use it.
Sample Code given below
this.props.history.push('/') //this will go to home page
or
this.props.history.goBack() //this will go to previous page
For your problem you try with push method and give the exact url you to move on.
For more reference visit https://reacttraining.com/react-router/web/api/history
What you want is this:
Let's say a person goes to a single page in your website such as: www.yoursite.com/category/books/romeo-and-juliet
In this page, you want to show a "Back" button that links you to one upper directory which is: www.yoursite.com/category/books/
This is breadcrumb system that we famously had in vBulletin forums and such.
Here is a basic solution to this:
let url = window.location.href;
let backButtonUrl = "";
if (url.charAt(url.length - 1) === "/") {
backButtonUrl = url.slice(0, url.lastIndexOf("/"));
backButtonUrl = backButtonUrl.slice(0, backButtonUrl.lastIndexOf("/"));
} else {
backButtonUrl = url.slice(0, url.lastIndexOf("/"));
}
What it basically does is:
1. Get the current URL from browser
2. Check if there is a "/" (slash) at the end of the link.
a. If there is: remove the slash, and remove everything the last slash
b. If there is not: remove everything last slash.
You can use {backButtonUrl} as your Go Back button link.
Note: it does not have anything to do with React Router, history, etc.
Note 2: Assuming you are using a link architecture that goes like www.site.com/word/letter/character
If you want to use it with react-router-dom library, then you need to set your url variable like this:
let url = this.props.match.url;
I found a solution. It's not beautiful but it works.
class Restaurant extends Component {
constructor(props) {
super(props);
this.props.history.push('/');
this.props.history.push(this.props.match.url);
}
...
I've had the same problem today. I have the following flow in one of the applications I'm working on:
User fills out a registration form
User enters credit card "payment page"
When payment is successful, the user sees a "payment confirmation" page.
I want to prevent the users from navigating from the "payment confirmation" (3) page back to any previous steps in the payment flow (1 and 2).
The best thing to do would be not to use routes to control which content is displayed, and use state instead. If you cannot afford to do that,
I found two practical ways to solve the problem:
Using React-Router:
When you hit the back button, React Router's history object will look like this:
When you go to any page using history.push record the page you are visiting in the state
Create a decorator, HOC, or whatever type of wrapper you prefer around the React-Router's Route component. In this component: If history.action === "POP" and "history.state.lastVisited === <some page with back navigation disabled>", then you should redirect your user to the /home page using history.replace
Another way to do is is by going to the /home page directly:
Use history.action to detect the back button was used, then:
Change location.href to equal the page you want to visit
Call location.reload(). This will reload the application, and the history will be reset
Browser back button works on your routes history. It will not invoke your programmatically handled routing. That's the point where we should keep maintain history stack with react router. If you are at route '/' and push '/home'. On browser back button it will pop '/home and will go back to '/'.
Even If you implementButton component for go back functionality and use react router history props. Believe me you have to carefully manage your navigation to maintain browser history stack appropriately. So it behaves same like whether you press browser back button or your app Button to go back or go forward.
I hope this would be helpful.
We wanted something similar for our React app and unfortunately this was the best solution we came up with. This is particularly helpful when our users are on mobile devices and they land on a specific page on our site from an ad or a referrer.
This is in our main routes.tsx file.
useEffect(() => {
// The path that the user is supposed to go to
const destinationPath = location.pathname;
// If our site was opened in a new window or tab and accessed directly
// OR the page before this one was NOT a page on our site, then...
if (
document.referrer === window.location.href ||
document.referrer.indexOf(window.location.host) === -1
) {
// Replaces the current pathname with the homepage
history.replace("/");
// Then pushes to the path the user was supposed to go to
history.push(destinationPath);
}
}, []);
Now when a user presses the back button, it takes the user to our homepage instead of being stuck within the "nested" route they were in.
NOTE: There are some small quirks with this implementation. Our app is also a Cordova app so we NEED to have our own back button. This implementation works well with our own back button but does not seem to work with the native browser's back button; hence, it worked well for our needs.

Resources