React js Navigate to another page with variable - reactjs

I try to go from one page to another in React and that works. Only I would also like to send data. I am new to React and have tried a few things but I cannot come up with the right solution.
As an example this is my index.js:
import React from "react";
import ReactDOM from "react-dom";
import { createBrowserHistory } from "history";
import { Router, Route, Switch, Redirect } from "react-router-dom";
import 'bootstrap/dist/css/bootstrap.min.css';
import Firebase from 'firebase';
import config from './firebase';
import choicePayment from 'views/choiceMenuPayment/choiceMenuPayment';
// core components
import Admin from "layouts/Admin.js";
import RTL from "layouts/RTL.js";
import "assets/css/material-dashboard-react.css?v=1.8.0";
const hist = createBrowserHistory();
ReactDOM.render(
<Router history={hist}>
<Switch>
<Route path="/admin" component={Admin} />
<Route exact path="/betalen/:test" component={choicePayment} />
<Redirect from="/" to="/admin/dashboard" />
</Switch>
</Router>,
document.getElementById("root")
);
This my internalRoutes.js:
import Dashboard from "#material-ui/icons/Dashboard";
import AddCircleOutlineIcon from '#material-ui/icons/AddCircleOutline';
import ExitToAppIcon from '#material-ui/icons/ExitToApp';
import CalendarToday from '#material-ui/icons/CalendarToday';
import EuroSymbol from '#material-ui/icons/EuroSymbol';
import Tune from '#material-ui/icons/Tune';
import AddIcon from '#material-ui/icons/Add';
// core components/views for Admin layout
import DashboardPage from "views/Dashboard/Dashboard.js";
import choicePayment from "views/choiceMenuPayment/choiceMenuPayment.js";
const internalRoutes = [
{
path: "/betalen",
name: "Keuze menu",
icon: Dashboard,
component: choicePayment,
layout: "/admin"
},
];
export default internalRoutes;
What I am trying to do is go from the ChaskDesk.js page to the choiceMenuPayment.js page when the link is clicked. For now that is possible with a variable "hello world", only this does not work, I would like that if the link is clicked in ChaskDesk.js the page choiceMenuPayment.js opens with the data "hello world" somewhere in the html as output. This is my current attempt, however, this does not work, is there anyone who can explain to me how I can make this?
The code on chaskdesk.js :
<Link to={{pathname: "/betalen",
state:{
name: "Hello Wolrd"
}}} component={internalRoutes} className="btn btn-primary">hello</Link>
the destination page:
import React, { useEffect } from "react";
import { useState } from 'react';
import { makeStyles } from "#material-ui/core/styles";
import styles from "assets/jss/material-dashboard-react/views/dashboardStyle.js";
import { Container } from "react-bootstrap";
import { Row } from "react-bootstrap";
import { Col } from "react-bootstrap";
import Close from '#material-ui/icons/Close';
import AddIcon from '#material-ui/icons/Add';
import RemoveIcon from '#material-ui/icons/Remove';
import { render } from "react-dom";
import { Button } from "react-bootstrap";
import { Link } from "react-router-dom";
import internalRoutes from "internalRoutes";
//const data = this.props.match.params.test;
export default function ChoicePayment() {
useEffect(()=> {
const {name} = this.props.location.state;
console.log(name);
})
return (
<div>
<Container >
<h3>Maak keuze</h3>
<Row>
<Col md={8} >
<form>
<Row>
<Col md={6}>
<label>
Klant:
</label>
<br/>
<Link to="/" className="btn btn-primary">hello</Link>
</Col>
</Row>
</form>
</Col>
</Row>
</Container>
</div>
);
}

Looks like you are merging class components (using this) with functional components.
The need to pass props into a functional component. Try changing ChoicePayment to something like this
export default function ChoicePayment(props) {
useEffect(()=> {
const {name} = props.location.state;
console.log(name);
})
...
You can always console log props outside of useEffect too
export default function ChoicePayment(props) {
console.log(props);
....
EDIT
This is working for me
const Admin = (props) => {
console.log(props);
return (
<div>
<div>Welcome to Admin</div>
<Link to={{ pathname: "/betalen", state: { name: "Hello Wolrd" } }} className="btn btn-primary">Test</Link>
</div>
);
}
function Test(props) {
console.log(props);
useEffect(() => {
const { name } = props.location.state;
console.log(name);
}, []);
return (
<div>
<div>Welcome to Test</div>
<Link to={{ pathname: "/admin" }} className="btn btn-primary">Admin</Link>
</div>
);
}
ReactDOM.render(
<Router history={hist}>
<Switch>
<Route path="/admin" component={Admin} />
<Route path="/betalen" component={Test} />
<Redirect from="/" to="/admin" />
</Switch>
</Router>,
document.getElementById("root")
);```

Related

Best practise: Where to put the Navbar component so that it -re-renders with every page?

This has been bugging me for a long time, and my head just can't seem to come up with a solution that works fluently. I will try to be short:
I have a React app where I update my Navbar based on an access token being stored as a cookie or not (user authenticated or not). But in order for my Navbar to update whether the user is authenticated, I have to refresh the page. I believe it is because my Navbar is being rendered way up (in?) the component tree, and does not get re-rendered whenever I visit a new page (only when I refresh).
What is the best way to render my Navbar component so that every page shares the same component, BUT the Navbar re-renders on every new page visited? Or is this even a wise thing to do?
Let me know if I am not explaining myself clearly.
index.jsx
import React from "react";
import ReactDOM from "react-dom";
import { App } from "./components/App";
import { BrowserRouter } from "react-router-dom";
import "./styles/styles.css";
import { PublicClientApplication } from "#azure/msal-browser";
import { MsalProvider } from "#azure/msal-react";
import { msalConfig } from "./lib/authConfig";
const msalInstance = new PublicClientApplication(msalConfig);
ReactDOM.render(
<MsalProvider instance={msalInstance}>
<BrowserRouter>
<App />
</BrowserRouter>
</MsalProvider>,
document.getElementById("root")
);
App.jsx
import React from "react";
import { Router } from "./Router";
import { Navbar } from "./Navbar";
export function App() {
return (
<div>
<Navbar />
<Router />
</div>
);
}
Router.jsx
import { Route } from "react-router-dom";
import React from "react";
import { MainPage } from "./MainPage";
import { LoginPage } from "./LoginPage";
import { GoogleLogin } from "./GoogleLogin";
import { GoogleLoginCallback } from "./GoogleLoginCallback";
import { GoogleLogout } from "./GoogleLogout";
import { NewArticle } from "./NewArticle";
export function Router() {
return (
<div>
<Route exact path="/" component={MainPage} />
<Route exact path="/login" component={LoginPage} />
<Route exact path="/login/google" component={GoogleLogin} />
<Route exact path="/logout/google" component={GoogleLogout} />
<Route exact path="/newArticle" component={NewArticle} />
<Route
exact
path="/login/google/callback"
component={GoogleLoginCallback}
/>
</div>
);
}
Navbar.jsx
import React, { useEffect, useState } from "react";
import { NavLink } from "react-router-dom";
import { useIsAuthenticated, useMsal } from "#azure/msal-react";
import { fetchJSON } from "../lib/fetchJSON";
export function Navbar() {
const activeStyle = {
borderBottom: "10px solid white",
};
const [username, setUsername] = useState();
const { accounts } = useMsal();
const name = accounts[0] && accounts[0].name;
const hasCookie = document.cookie.startsWith("access_token");
const isAuthenticated = useIsAuthenticated();
useEffect(async () => {
const res = await fetchJSON("/api/login/google");
if (hasCookie) {
setUsername(res.userinfo.given_name);
}
}, []);
return (
<>
<div className={"navbar-container"}>
<NavLink exact to="/" activeStyle={activeStyle}>
Home
</NavLink>
<NavLink exact to="/login" activeStyle={activeStyle}>
Login-portal
</NavLink>
{isAuthenticated ? (
<NavLink exact to="/newArticle" activeStyle={activeStyle}>
New Article
</NavLink>
) : (
<div />
)}
{isAuthenticated || hasCookie ? (
<p className="logged-in">
Logged in as {username} {name}
</p>
) : (
<p className="logged-in">Not logged in</p>
)}
</div>
</>
);
}

Trying to add a live website URL in ReactJs

I am trying to add the live website URL i.e "https://covid19statswebsite.netlify.app/" so that when I click on my Button it should redirect me to the above URL. How can I do that?
Any Suggestions?
below is my Button,
import React from "react";
import "./Banner.css"
import BannerVideo from './videos/video-2.mp4'
import {Button} from "react-bootstrap";
import {useHistory} from "react-router-dom";
// import axios from './axios'
// import requests from "./Request";
function Banner(){
const history = useHistory()
return(
<div className="banner-container">
<video src={BannerVideo} autoPlay loop muted/>
<h1>ADVENTURE AWAITS</h1>
<p>What are you waiting for?</p>
/////////// Button That needs to redirect it ///////////////////////////////////////////////////////
<div className="banner-buttons">
<br/><br/><Button onClick={() => history.push("/covid")} className="covid"><span>COVID-19 Status</span></Button>
</div>
</div>
);
}
export default Banner
This is my App.js file which imports the Banner.js file above for Routes. I am not sure that the thing I want will happen with Routes or not. So I'd really love to know any other alternative if present.
import React, {useEffect} from 'react';
import './App.css';
import HomeScreen from "./screens/HomeScreen";
import LoginScreen from "./screens/LoginScreen";
import ProfileScreen from "./screens/ProfileScreen"
import {auth} from "./firebase";
import {BrowserRouter as Router, Switch, Route} from 'react-router-dom';
import {useDispatch, useSelector} from "react-redux";
import {login, logout, selectUser} from "./features/userSlice";
import Spain from "./countries/Spain";
import Covid from './Covid.js'
function App() {
const user = useSelector(selectUser)
const dispatch = useDispatch();
useEffect(() => {
const unsubscribe = auth.onAuthStateChanged(userAuth => {
if (userAuth){
dispatch(login({
uid: userAuth.uid,
email: userAuth.email
}))
}else {
dispatch(logout());
}
});
return unsubscribe
}, [dispatch]);
return (
<div className="App">
<Router>
{!user ? (
<LoginScreen/>
):(
<Switch>
<Route path="/profile">
<ProfileScreen/>
</Route>
<Route exact path="/">
<HomeScreen/>
</Route>
<Route path="/spain">
<Spain/>
</Route>
//////////////////// Covid part //////////////////////////////////////////////////////////
<Route path="/covid">
<Covid/>
</Route>
</Switch>
)}
</Router>
</div>
);
}
export default App;
Below is the Covid.js which I created to check whether the Route works or not.
import React from "react";
function Covid(){
return(
<div className="covid">
<h1>hello</h1>
</div>
)
}
export default Covid
Edit:
import { Link } from "react-router-dom";
<Link
to={{
pathname:
"https://.......",}}
target="_blank">
<Button>...</Button>
</Link>
try to put the link in a hyperlink.
<a
href="https://covid19statswebsite.netlify.app/"
target="_blank">
<Button>...</Button>
</a>

React Router: Changes URL but does not render component

As a newbie to React and Material-UI, I'm desperated about a routing problem.
When the button is clicked, the URL changes - but the component does not render for some reason. I've tried nearly every possible solution provided here on StackOverflow. Nothing works. Maybe you can find the problem?
Here is my code:
import React from 'react'
import { Button } from '#material-ui/core'
import { BrowserRouter } from 'react-router-dom'
import { Link, LinkProps } from 'react-router-dom'
const Spielwiese = React.forwardRef<HTMLAnchorElement, LinkProps>(
(props, ref) => <Link innerRef={ref as any} {...props} />
)
const Favoriten = React.forwardRef<HTMLAnchorElement, LinkProps>(
(props, ref) => <Link innerRef={ref as any} {...props} />
)
const LandingPage = () => {
const classes = useStyles()
return (
<div className="App">
<BrowserRouter>
<Button
component={Spielwiese}
to="/spielwiese"
>
Dinge finden!
</Button>
<Button
component={Favoriten}
to="/favoriten"
>
Meine Favoriten!
</Button>
</BrowserRouter>
</div>
)
}
export default LandingPage
Thanks a lot in advance!
You have to define Routes for each of your components inside a BrowserRouter. Otherwise, you cannot navigate your App.
See sandbox for solution: https://codesandbox.io/s/unruffled-flower-to9jd
Additionally, you should separate the LandingPage content into its own component. Then you will define a Route for that component as well.
App.js
import React from "react";
import ReactDOM from "react-dom";
import { BrowserRouter, Route } from "react-router-dom";
import LandingPage from "./LandingPage";
import Spielwiese from "./Spielwiese";
import Favoriten from "./Favoriten";
const App = () => {
return (
<div className="App">
<BrowserRouter>
<Route component={LandingPage} path="/" exact />
<Route component={Spielwiese} path="/spielwiese" />
<Route component={Favoriten} path="/favoriten" />
</BrowserRouter>
</div>
);
};
export default LandingPage;
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
LandingPage.js
import React from "react";
import { Button } from "#material-ui/core";
import { Link } from "react-router-dom";
const LandingPage = () => {
return (
<div className="App">
<Link to="/spielwiese">
<Button>Dinge finden!</Button>
</Link>
<Link to="/favoriten">
<Button>Meine Favoriten!</Button>
</Link>
</div>
);
};
export default LandingPage;
Well, I cannot see the difference between Spielwiese and Favoriten that's maybe the reason :)?

props.history.push() doesn't redirect

props.history.push("/") doesn't redirect.
I did search for solution for this problem and can't find where is the problem and that drives me crazy.
index.js
import 'bootstrap/dist/css/bootstrap.css';
import 'bootstrap/dist/css/bootstrap-theme.css';
import './index.css';
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { ConnectedRouter } from 'react-router-redux';
import { createBrowserHistory } from 'history';
import configureStore from './store/configureStore';
import App from './App';
//import registerServiceWorker from './registerServiceWorker';
// Create browser history to use in the Redux store
const baseUrl = document.getElementsByTagName('base')[0].getAttribute('href');
const history = createBrowserHistory({ basename: baseUrl });
// Get the application-wide store instance, prepopulating with state from the server where available.
const initialState = window.initialReduxState;
const store = configureStore(history, initialState);
//Render app on "root" <div> in index.html
ReactDOM.render(
<Provider store={store}>
<ConnectedRouter history={history}>
<App />
</ConnectedRouter>
</Provider>,
document.getElementById('root'));
//registerServiceWorker();
app.js
import React from 'react';
import { Route, Switch } from 'react-router';
import Home from './components/Home';
import Login from './components/Login/Login';
import Counter from './components/Counter';
import FetchData from './components/FetchData';
import { PrivateRoute } from './components/PrivateRoutes/PrivateRoute';
const App = (props) => {
return (
<Switch>
<Route path="/login" component={Login}/>
<PrivateRoute path="/" component={Home} />
<Route path='/counter' component={Counter} />
<Route path='/fetchdata/:startDateIndex?' component={FetchData} />
</Switch>
);
}
export default App;
Login.js
import React, { useState } from 'react';
import { withRouter, Redirect, history } from 'react-router-dom'
import { Form, Label, FormGroup, FormControl, Button } from 'react-bootstrap';
import Home from '../Home';
//Login user
function LoginUser(username, password, callback) {
console.log("Atemt to login..." + " " + username);
fetch('api/SampleData/Login', {
method: "POST",
body: JSON.stringify({
email: username,
password: password,
})
}).then(response => response.json())
.then(json =>callback(json))
}
function Login(props) {
var logged = false;
var data = { username: '', password: '', };
function getUsername(event) {
data.username = event.target.value;
console.log(data);
}
function getPassword(event) {
data.password = event.target.value;
console.log(data);
}
function requestCallback(res) {
if (res[0] === "connected") {
props.history.push('/');
console.log(props.history);
}
}
if (logged === true) {
return (<Redirect to="/" component={Home} />);
}
return (
<div style={{ position: 'absolute', left: '50%', top: '50%', transform: 'translate(-50%, -50%)' }}>
<Form >
<FormGroup controlId="formBasicEmail">
<Label>Email address</Label>
<FormControl type="email" placeholder="Enter email" onChange={getUsername} />
</FormGroup>
<FormGroup controlId="formBasicPassword">
<Label>Password</Label>
<FormControl type="password" placeholder="Password" onChange={getPassword} />
</FormGroup>
<Button variant="primary" onClick={() => LoginUser(data.username, data.password, requestCallback)} style={{ margin: '0 auto', display: 'block', width: '100px' }}>
Login
</Button>
</Form>
</div>
);
}
export default withRouter(Login);
As you can see Login component is wrapped with withRouter(Login). console.log(props) in Login.js file shows that history is passed to props.
The problem is that in your PrivateRoute you have a constant variable called userLogged which is initiated with the value false. If the variable is true, the defined component is rendered. If it is false, you redirect ot /login.
The value of userLogged is always false, so you always redirect to /login. I recommend you handle your logged-in state either in your parent component App or through the usage of a store from redux.
Use 'history' npm package
1)App.js
import React, { Component } from "react";
import { Route, Router } from "react-router-dom";
import { createBrowserHistory } from "history";
import Dashboard from "./components/dashboard.js ";
import Login from "./components/login.js";
import Profile from "./components/profile.js";
import PrivateRoute from "./privateRoute.js";
export const history = createBrowserHistory();
//refer 'history' for wanted component like profile.js
class App extends Component {
render() {
return (
<Router history={history}>
<div>
<PrivateRoute
path="/"
component={Dashboard}
exact
/>
<Route path="/login" component={Login} exact />
<PrivateRoute path="/profile" component={Profile} />
</div>
</Router>
);
}
}
export default App;
a)Once you login store some data in local Storage with key "user".
b)Based on this "user" object in localStorage routing will happen in prBivateRoute.js
c)If you want to log out clear localStorage it will navigate into loginPage
2)privateRoute.js
import React from "react";
import { Route, Redirect } from "react-router-dom";
const PrivateRoute = ({ component: Component, ...rest }) => {
return (
<Route
{...rest}
render={props => {
if (localStorage.getItem("user")!= "") {
return <Component />;
}else {
return <Redirect to={{ pathname: "/login" }} />;
}
}}
/>
);
};
3)profile.js
import React, { Component } from "react";
import { history } from "./App.js";
class Profile extends Component {
goBack = () => {
history.push("/");
};
render() {
<button onClick={() => this.goBack()}> back to dashboard </button>;
}
}
export default Profile;

React Router changes Link but doesnt render proper component

Hello I'm working with React Router... I have two components App.js and SideNavComponent. I want to click the link in the SideNavComponent to and travel to the correct Component.
Right now when I click on the Link it changes the URL but does not render the correct component. However if I change the URL myself the correct view renders.
App.js
import React, { Component } from 'react';
import { Col, Well, Panel } from 'react-bootstrap';
import NavbarComponent from './NavbarComponent';
import SideNavComponent from './SideNavComponent';
import Router from './Router';
class App extends Component {
render() {
return (
<div>
<div className="header">
<NavbarComponent />
</div>
<div className="body">
<Col md={3}>
<Well>
<SideNavComponent />
</Well>
</Col>
<Col md={9}>
<Panel>
<Router />
</Panel>
</Col>
</div>
<div className="footer" />
</div>
);
}
}
export default App;
SideNavComponent
import React, { Component } from 'react';
import { Nav, NavItem } from 'react-bootstrap';
import { Link, BrowserRouter, Switch } from 'react-router-dom';
class SideNavComponent extends Component {
state = {
selectedLink: 1
};
selectLink(key) {
this.setState({ selectedLink: key });
}
render() {
return (
<BrowserRouter>
<div style={{ flexDirection: 'column' }}>
<Link to="/">Home</Link>
<Link to="/device">Device</Link>
<Link to="/transform">Transformation</Link>
<Link to="/graph">Graphs</Link>
</div>
</BrowserRouter>
);
}
}
export default SideNavComponent;
Router.js
import React from 'react';
import { BrowserRouter, Route, Switch } from 'react-router-dom';
import HomeComponent from './pages/HomeComponent';
import DeviceComponent from './pages/DeviceComponent';
import TransformationComponent from './pages/TransformationComponent';
import GraphComponent from './pages/GraphComponent';
const Router = () => {
return (
<BrowserRouter>
<div>
<Switch>
<Route path="/device" component={DeviceComponent} />
<Route path="/transform" component={TransformationComponent} />
<Route path="/graph" component={GraphComponent} />
<Route exact path="/" component={HomeComponent} />
</Switch>
</div>
</BrowserRouter>
);
};
export default Router;
The problem is you have multiple instances of browser router and history is getting confused. You can fix this by re-organising the structure of application like the below example.
// *-----------------------*
// | MAIN-APP COMPONENT |
// *-----------------------*
import React, { Component } from "react";
import { Col, Well, Panel } from "react-bootstrap";
import { Route, Switch } from "react-router-dom";
import SideNavComponent from "./SideNavComponent";
const HomeComponent = () => <div>Home</div>;
const GraphComponent = () => <div>Graph</div>;
const DeviceComponent = () => <div>Device</div>;
const TransformationComponent = () => <div>Transformation</div>;
class App extends Component {
render() {
return (
<div>
<div className="header" />
<div className="body">
<Col md={3}>
<Well>
<SideNavComponent />
</Well>
</Col>
<Col md={9}>
<Panel>
<Switch>
<Route path="/device" component={DeviceComponent} />
<Route path="/transform" component={TransformationComponent} />
<Route path="/graph" component={GraphComponent} />
<Route exact path="/" component={HomeComponent} />
</Switch>
</Panel>
</Col>
</div>
<div className="footer" />
</div>
);
}
}
export default App;
// *-----------------------*
// | SIDENAV-COMPONENT |
// *-----------------------*
import React, { Component } from "react";
import { Nav, NavItem } from "react-bootstrap";
import { Link } from "react-router-dom";
class SideNavComponent extends Component {
render() {
return (
<div style={{ flexDirection: "column" }}>
<Link to="/">Home</Link>
<Link to="/graph">Graphs</Link>
</div>
);
}
}
export default SideNavComponent;
// *-----------------------*
// | MAIN.JS (ENTRY POINT) |
// *-----------------------*
import React from 'react'
import { render } from 'react-dom'
import App from './components/App';
import { BrowserRouter } from 'react-router-dom';
render((
<BrowserRouter>
<App />
</BrowserRouter>
), document.getElementById('root'));

Resources