React router: component not rendering after login - javascript

I'm building a website using React and I'm trying to redirect the user to the index page after the login, but my component is not rendering anything, although I'm being redirected and I can see the URL changing from /welcome#/login to /main.
Since I'm not getting any error messages and the webpack is being successfully compiled, I can't see what's wrong anymore.
Any ideas of what could possibly be wrong?
Thank you very much!
Start.js
import React from "react";
import ReactDOM from "react-dom";
import Welcome from "./welcome";
import { App } from "./app";
import { Provider } from "react-redux";
import { createStore, applyMiddleware } from "redux";
import reduxPromise from "redux-promise";
import { composeWithDevTools } from "redux-devtools-extension";
import reducer from "./reducer";
const store = createStore(
reducer,
composeWithDevTools(applyMiddleware(reduxPromise))
);
let element;
if (location.pathname === "/welcome") {
element = <Welcome />;
} else {
init(store);
element = (
<Provider store={store}>
<App />
</Provider>
);
}
ReactDOM.render(element, document.querySelector("main"));
Welcome.js
import React from "react";
import Register from "./register";
import Login from "./login";
import { HashRouter, Route, Redirect } from "react-router-dom";
export default class Welcome extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<HashRouter>
<div className="register-wrapper">
<div>
<Route path="/login" component={Login} />
<Route exact path="/" component={Register} />
</div>
</div>
</HashRouter>
);
}
}
Login Component
import React from "react";
import axios from "./axios";
export default class Login extends React.Component {
constructor(props) {
super(props);
this.state = { error: false };
this.loginButton = this.loginButton.bind(this);
this.handleChange = this.handleChange.bind(this);
}
loginButton(e) {
e.preventDefault();
axios
.post("/login", this.state)
.then(res => {
if (res.data.success) {
location.replace("/main");
} else {
this.setState({
error: true
});
}
})
.catch(error => console.log(error));
}
handleChange(e) {
this.setState(
{
[e.target.name]: e.target.value
},
() => console.log("this.state:", this.state)
);
}
render() {
return (
<div className="login-main-container">
{this.state.error && <h2>Ops! Something went wrong.</h2>}
<h1 className="login-title">Kathi & Rodolfo</h1>
<h2 className="login-subtitle">Dear guest, please login first</h2>
<div className="login-container">
<form className="login-form">
<label className="label-login" htmlFor="email"> username </label>
<input className="input-login"
name="email"
placeholder="Best Couple You Know"
onChange={this.handleChange}
/>
<label className="label-login" htmlFor="password"> password </label>
<input className="input-login"
name="password"
type="password"
placeholder="Super Loving Password"
onChange={this.handleChange}
/>
<button
className="login-button"
onClick={this.loginButton}
>
Login
</button>
</form>
</div>
<h4 className="login-info">Information about username and password can be found on the Save The Date card</h4>
</div>
);
}
}
Index Component (Main)
import React from "react";
export default class Main extends React.Component {
constructor(props) {
super(props);
this.state ={ error: false};
}
render () {
return (
<div className="main-container">
<header>
<p>the wedding</p>
<p>rpsv</p>
<p>contact us</p>
<p>wedding gift</p>
</header>
{this.state.error && <h2>Ops! Something went wrong.</h2>}
<div className="save-the-date-img">
<h1>Save The Date</h1>
</div>
</div>
);
}
}
App.js
import React from "react";
import { BrowserRouter, Route, Link } from "react-router-dom";
import Main from "./main";
export class App extends React.Component {
constructor() {
super();
this.state = {};
}
render() {
return (
<BrowserRouter>
<div>
<Route exact path="/main" Component={Main}/>
</div>
</BrowserRouter>
);
}
}

location.replace("/main");
I think this line is wrong in your code.
While you are using React, you'd rather use react-router-dom's functionality than browser built-in feature.
Change the line to this.props.history.push('/main')

Give your file structure. Your component Login is not in BrowserRouter, but must be. Check the official sample: https://reacttraining.com/react-router/web/guides/quick-start.

instead of
location.replace("/main");
use
history.push("/main")

Related

Blank screen after using react <Provider>

I am trying to make a webpage using React js and use redux template. I am trying to wrap my component around < Provider >. After wrapping i get a blank page. I tried using React developer tools that too appears blank. here is my code. I have tried different methods nut none of them works.
Main.js
import Title from './Title'
import Photowall from './Photowall'
import AddPhoto from './AddPhoto'
import { Route } from 'react-router-dom'
class Main extends Component{
constructor(){
super()
this.state= {
posts : [{
id: "0",
description: "beautiful landscape",
imageLink: "https://image.jimcdn.com/app/cms/image/transf/none/path/sa6549607c78f5c11/image/i4eeacaa2dbf12d6d/version/1490299332/most-beautiful-landscapes-in-europe-lofoten-european-best-destinations-copyright-iakov-kalinin.jpg" +
"3919321_1443393332_n.jpg"
}, {
id: "1",
description: "Aliens???",
imageLink: "https://s3.india.com/wp-content/uploads/2017/12/rocket.jpg"
}, {
id: "2",
description: "On a vacation!",
imageLink: "https://fm.cnbc.com/applications/cnbc.com/resources/img/editorial/2017/08/24/104670887-VacationExplainsTHUMBWEB.1910x1000.jpg"
}],
}
this.removePhoto=this.removePhoto.bind(this)
}
removePhoto(postRemoved){
console.log(postRemoved.description)
this.setState((state) => ({
posts: state.posts.filter(post => post !== postRemoved)
}))
}
addPhoto(postSubmitted){
this.setState(state => ({
posts:state.posts.concat([postSubmitted])
}))
}
componentDidMount(){
}
componentDidUpdate(prevProps,prevState){
console.log(prevState.posts)
console.log(this.state)
}
render() {
return (
<div>
<Route exact path="/" render={() => (
<div>
<Title title={'Photowall'}/>
<Photowall posts={this.state.posts} onRemovePhoto={this.removePhoto} onNavigate={this.navigate}/>
</div>
)}/>
<Route path="/AddPhoto" render={({history})=>(
<AddPhoto onAddPhoto={(addedPost)=>{
this.addPhoto(addedPost)
history.push('/')
}}/>
)}/>
</div>
)
}
}
export default Main
AddPhoto.js
import React, { Component } from "react"
class AddPhoto extends Component{
constructor(){
super()
this.handleSubmit=this.handleSubmit.bind(this)
}
handleSubmit(event){
event.preventDefault();
const imageLink = event.target.elements.link.value
const description = event.target.elements.description.value
const post = {
id:0,
description:description,
imageLink:imageLink
}
if(description && imageLink){
this.props.onAddPhoto(post)
}
}
render(){
return(
<div>
<h1>Photowall</h1>
<div className="form">
<form onSubmit={this.handleSubmit}>
<input type="text" placeholder="Link" name="link"/>
<input type="text" placeholder="Description" name="description"/>
<button>Post</button>
</form>
</div>
</div>
)
}
}
export default AddPhoto
Photo.js
import React, {Component} from "react";
import PropTypes from 'prop-types'
function Photo(props){
const post =props.post
return <figure className="figure">
<img className="photo" src={post.imageLink} alt={post.description}/>
<figcaption><p>{post.description}</p></figcaption>
<div className="button-container">
<button className="remove-button" onClick={()=>{
props.onRemovePhoto(post);
}}> Remove </button>
</div>
</figure>
}
Photo.propTypes={
post: PropTypes.object.isRequired,
onRemovePhoto:PropTypes.func.isRequired
}
export default Photo
Photowall.js
import React,{ Component} from 'react'
import Photo from './Photo'
import PropTypes from 'prop-types'
import {Link} from 'react-router-dom'
function Photowall(props){
return <div>
<Link className='addIcon' to='/AddPhoto' ><img src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij48cGF0aCBkPSJNMTIgMGMtNi42MjcgMC0xMiA1LjM3My0xMiAxMnM1LjM3MyAxMiAxMiAxMiAxMi01LjM3MyAxMi0xMi01LjM3My0xMi0xMi0xMnptNyAxNGgtNXY1aC00di01aC01di00aDV2LTVoNHY1aDV2NHoiLz48L3N2Zz4="></img> </Link>
{/*<button onClick={props.onNavigate} className='addIcon'> + </button>*/}
<div className='photo-grid'>
{props.posts.map((post, index) => <Photo key={index} post={post} onRemovePhoto={props.onRemovePhoto}/>)}
</div>
</div>
}
Photowall.propTypes={
posts: PropTypes.array.isRequired,
onRemovePhoto:PropTypes.func.isRequired
}
export default Photowall
index.js
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import Main from './Components/Main'
import './styles/stylesheet.css'
import {BrowserRouter} from 'react-router-dom'
import {createStore} from 'redux'
import rootReducer from './redux/reducer'
import {Provider} from "react-redux";
const store = createStore(rootReducer)
ReactDOM.render(<Provider store={store}><BrowserRouter><Main/></BrowserRouter></Provider>, document.getElementById('root'));
reducer.js
import posts from '../data/posts'
const postReducer = function posts(state = posts,action){
return state
}
export default postReducer

How to navigate to homepage upon form submit in react web using react-router-dom v6.2.1?

I have a Smart component class page PhoneDirectory.js, where I have used BrowserRouter and Route to route to the ShowSubscribers page("/") and AddSubscribers page ("/add"). My requirement is to redirect to the ShowSubscribers page("/") upon form submission on the AddSubscribers page but not understand how to implement that. I tried using this.props.history.push("/") but it isn't working. I am new to React, can anyone please help?
import React from 'react';
import AddSubscriber from './AddSubscriber';
import ShowSubscribers from './ShowSubscribers';
import {BrowserRouter , Route, Routes} from 'react-router-dom';
export default class PhoneDirectory extends React.Component{
constructor(){
super();
this.state = {[]};
}
addSubscribers = (subscribers) =>{...}
deleteSubscribers = (subscriberId) =>{...}
render() {
return (
<BrowserRouter>
<Routes>
<Route exact path='/' element={<ShowSubscribers deleteSubscribers={this.deleteSubscribers} subscribersList={this.state.subscribersList}/>}/>
<Route exact path='/add' element={<AddSubscriber addSubscribers={this.addSubscribers}/>}/>
</Routes>
</BrowserRouter>
)
}
}
Dumb component AddSubscriber page
import React from 'react';
import Header from './Header';
import './AddSubscriber.css';
import {Link} from "react-router-dom";
export default class AddSubscriber extends React.Component {
constructor() {
super();
this.state = {
id: 0,
name:'',
phone:''
}
}
onChangeHandler = (event) =>{...}
onFormSubmitted = (event) =>{
event.preventDefault();
this.props.addSubscribers(this.state);
this.setState({id:0, name:"", phone:''});
// Need logic to redirect to "/" i.e., ShowSubscribers page
}
render() {
return (<div>
<Header heading="Add Subscriber"/>
<div className="component-body-container">
<Link to="/">
<button className="custom-btn">Back</button>
</Link>
<form className="subscriber-form" onSubmit={this.onFormSubmitted.bind(this)}>
...............
<button type="submit" className="custom-btn add-btn">Add</button>
</div>
</form>
</div>
</div>)}
}
I tried this.props.history.push("/"), but it didn't worked.
react-router-dom v6 support only hooks version i suggest since you use class component to downgrade the version of react-router-dom in package.json.
"dependencies": {
...
"react-router-dom": "5.2.1",
},
Now you need to run : npm install or yarn install
Your Route component will look like that
import React from 'react';
import AddSubscriber from './AddSubscriber';
import ShowSubscribers from './ShowSubscribers';
import { Route, Switch, BrowserRouter as Router } from 'react-router-dom';
export default class PhoneDirectory extends React.Component{
constructor(){
super();
this.state = {[]};
}
addSubscribers = (subscribers) =>{...}
deleteSubscribers = (subscriberId) =>{...}
render() {
return (
<Router>
<Switch>
<Route exact path='/'>
<ShowSubscribers {...your props goes here}/>
</Route>
<Route exact path='/add'>
<AddSubscriber {...your props goes here}/>
</Route>
</Switch>
</Router>
)
}
}
Now you are able to call this.props.history.push
import React from 'react';
import Header from './Header';
import './AddSubscriber.css';
export default class AddSubscriber extends React.Component {
constructor() {
super();
this.state = {
id: 0,
name:'',
phone:''
}
}
onChangeHandler = (event) =>{...}
onFormSubmitted = (event) =>{
event.preventDefault();
this.props.addSubscribers(this.state);
this.setState({id:0, name:"", phone:''});
// Need logic to redirect to "/" i.e., ShowSubscribers page
}
render() {
return (<div>
<Header heading="Add Subscriber"/>
<div className="component-body-container">
<button className="custom-btn" onClick={()=>this.props.history.push('/')} >Back</button>
<form className="subscriber-form" onSubmit={this.onFormSubmitted.bind(this)}>
...............
<button type="submit" className="custom-btn add-btn">Add</button>
</div>
</form>
</div>
</div>)}
}
I think that you need to wrap your AddSubscriber page with withRouter HOC
class AddSubscriber extends React.Component{
...some-code....
}
export default withRouter(AddSubscriber)
you need navigation logic (this.props.history.push("/"))
to be located a addScubscribers page.
(you have it at "homepage" instead)

oktaAuth with react stuck in login/callback

I am using
"#okta/okta-auth-js": "^5.8.0",
"#okta/okta-react": "^6.3.0",
in my react app.
This is my App.js:
import React, { Component } from 'react';
import { Router } from 'react-router-dom';
import AppWithRouterAccess from './AppWithRouterAccess';
import history from './data/history';
class App extends Component {
render() {
return (
<Router history={history}>
<AppWithRouterAccess />
</Router>
);
}
}
export default App;
(history is just export default createBrowserHistory();
AppWithRouterAccess.js :
import React, { Component } from 'react';
import { Route, withRouter, Switch } from 'react-router-dom';
import { Security, SecureRoute, LoginCallback } from '#okta/okta-react';
import { OktaAuth, toRelativeUrl } from '#okta/okta-auth-js';
import NavBar from './components/NavBar';
import './App.css'
import Home from './pages/Home';
import Enrichment from './pages/Enrichment';
import PrePublish from './pages/PrePublish';
import Published from './pages/Published';
import CheckPublication from './pages/CheckPublication';
import SignIn from './pages/SignIn';
import history from './data/history';
const OktaCred = require('./data/idc_cred.json')
export default withRouter(class AppWithRouterAccess extends Component {
constructor(props) {
super(props);
this.state={
is_logged: false
}
this.onAuthRequired = this.onAuthRequired.bind(this);
this.oktaAuth = new OktaAuth({
clientId: OktaCred.clientId,
issuer: OktaCred.issuer,
redirectUri: OktaCred.redirectUri,
scopes: ['openid', 'profile', 'email'],
postLogoutRedirectUr: OktaCred.postLogoutRedirectUri
});
}
onAuthRequired = () => {
history.push('/login');
}
restoreOriginalUri = async(_oktaAuth, originalUri) => {
history.replace(toRelativeUrl(originalUri, window.location.origin));
};
render() {
return (
<>
{this.state.is_logged?
<NavBar/>:undefined}
<Security oktaAuth={this.oktaAuth} restoreOriginalUri={this.restoreOriginalUri}>
<Switch>
<SecureRoute path='/' exact component={Home}/>
<Route path='/login' render={()=><SignIn />} />
<Route path='/login/callback' component={LoginCallback} />
</Switch>
</Security>
</>
);
}
});
idc_cred.json is a JSON file with all the Okta credentials (tested and works!)
SignIn.jsx is:
import React, { Component } from 'react';
import { Redirect } from 'react-router-dom';
import SignInForm from '../components/SignInForm.jsx';
import { withOktaAuth } from '#okta/okta-react';
export default withOktaAuth(class SignIn extends Component {
render() {
if (!this.props.authState) {
return <div>Loading...</div>;
}
return this.props.oktaAuth.isAuthenticated ?
<Redirect to="/"/> :
<SignInForm />;
}
});
and finally, SignInForm.jsx is:
import React, {Component} from "react";
import './styles/SignInForm.css';
import { withOktaAuth } from '#okta/okta-react'
import Logo from '../assets/Jfrog-Logo.svg'
export default withOktaAuth( class SignInForm extends Component{
constructor(props){
super(props);
this.state={
sessionToken: null,
username: '',
password: '',
};
this.handleSubmit = this.handleSubmit.bind(this);
this.handleUsernameChange = this.handleUsernameChange.bind(this);
this.handlePasswordChange = this.handlePasswordChange.bind(this);
}
handleSubmit = async (e) => {
e.preventDefault();
console.log(this.state)
this.props.oktaAuth.signInWithCredentials({
username: this.state.username,
password: this.state.password
})
.then(transaction => {
var pushFactor = transaction.factors.find(function(factor) {
return factor.provider === 'OKTA' && factor.factorType === 'push';
});
pushFactor.verify({
autoPush: true
})
console.log(transaction)
if(transaction.sessionToken){
this.setState(
{ sessionToken: transaction.sessionToken },
() => {
this.props.oktaAuth.signInWithRedicred({sessionToken: transaction.sessionToken})
}
)
}
})
.catch(err => console.log('Found an error', err));
}
handleUsernameChange = (e) => {
this.setState({username: e.target.value});
}
handlePasswordChange = (e) => {
this.setState({password: e.target.value});
}
render(){
if (this.state.sessionToken) {
return null;
}
return(
<div className="login-container">
<div className="total-login">
<div className="logo-login">
<img src={Logo} alt="logo" className="logo-self-login"/>
</div>
<div className="login-form-main">
<form onSubmit={this.handleSubmit}>
<p className="login-title">Login with Okta</p>
<label>
<p className="login-sub-title">Username:</p>
<input className="login-input" id="username" type="text" value={this.state.username} onChange={this.handleUsernameChange}/>
</label>
<label>
<p className="login-sub-title">Password:</p>
<input id="password" type="password" className="login-input" value={this.state.password} onChange={this.handlePasswordChange}/>
</label>
<br/>
<button className="login-button" type="submit" id="submit" value="Submit">Login</button>
<div/>
</form>
</div>
</div>
</div>
);
}
})
When the user enters his creds, the page becomes a blank page with Loading..., like so:
What am I missing?
Thanks!
The network tab:

calling a function from two different pages

i made a react web app , it should hide the navigation bar on login page then it should reappear after a successful login in all other other pages. The way i made the header hidden in login page is by making a function , but the login button is located in another page (Authen.js) and the function is located in App.js my problem is that i can't call the function from the first page to the other .
./src/App.js
Line 69: 'operation' is not defined no-undef
import React, { Component } from 'react';
import './App.css';
import Authen from './Pages/Authen'
import Home from './Pages/Home';
import secondpage from './Pages/secondpage';
import {
BrowserRouter as Router,
Route,
Link
} from 'react-router-dom';
var firebase = require('firebase');
class App extends Component {
constructor(props){
super(props);
this.state = {
ShowMe:false
};
}
operation(){
this.setState({
ShowMe:true
})
}
render(){
return(
<div>
<Router >
<div>
<div>
{
this.state.ShowMe?
<ul>
<li><Link to="/Home">Home</Link></li>
<li><Link to="/secondpage">secondpage</Link></li>
</ul>
:null
}
</div>
<Route exact path="/" component={Authen}/>
<Route path="/Home" component={Home}/>
<Route path="/secondpage" component={secondpage}/>
</div>
</Router>
</div>
);
}
}
export default App;
the login page :
import React, {Component} from 'react';
import {withRouter} from 'react-router-dom'
import {operation} from '../App'
var firebase = require('firebase');
class Authen extends React.Component {
Login = () => {
//login method
const email = this.refs.email.value;
const password = this.refs.password.value;
console.log(email,password);
const auth = firebase.auth();
const promise = auth.signInWithEmailAndPassword(email, password);
promise.catch(e =>{
var err = e.message;
console.log(err);
this.setState({err: err});
});
//gets user uid
firebase.auth().onAuthStateChanged((user) => {
if (user) {
console.log(user.uid);
this.props.history.push('/Home');
operation();
}
});
}
constructor(props){
super(props);
this.state = {
err:''
};
this.Login = this.Login.bind(this);
}
render(){
return(
<div className="login_div">
<div className="main-div">
<h3>N.N.NASSAR</h3>
<input ref="email" type="email" placeholder="Email..." id="email_field" />
<input ref="password" type="password" placeholder="Password..." id="password_field" />
<p>{this.state.err}</p>
<button onClick={() => this.Login() || this.operation()} id="Login"> Login </button>
<button onClick={this.signup}>Sign Up</button>
</div>
</div>
);
}
}
export default withRouter(Authen);
thank you for your time :)
If I understand your question, you want to call the 'operation' method of App from another component, and the reason you want to do that is because you want to set App's state from both App and from the other component.
One simple way to do it is by using redux and accessing the global state in the redux store, where you will save the state that you want to updare from both components.

Passing state value from component to component?

I've seen many answer on this website and in official docs and many other places. But I couldn't able to achieve results. That's why I'm posting this question.
SO, my question is I have 3 files named:
App.js, SignUp.js and Welcome.js.
My task is to get value in form from SignUp.js page and print that value to the Welcome.js component. I read about lifting state up and higher order components but couldn't able to do it.
Any help is appreciated.
Here's my code:
App.js:
import React,{Component} from "react";
import {BrowserRouter as Router, Link, Switch, Route} from "react-router-dom";
import SignUp from './SignUp';
import Welcome from './Welcome';
class App extends Component {
render(){
var homeMessage = () =>{
return(<div><SignUp /></div>);
}
return(
<Router>
<div>
<Route exact path="/src/Welcome" component={Welcome}/>
<Route exact path="/" component={homeMessage}/>
</div>
</Router>
);
}
}
export default App;
SignUp.js;
import React,{Component} from "react";
import {Link} from "react-router-dom";
export default class SignUp extends Component {
constructor(props){
super(props);
this.state = {
firstName:''
};
}
inputData = event =>
{
this.setState({
[event.target.name]:event.target.value
});
}
submitData = event =>
{
event.preventDefault();
}
render(){
return(
<div>
<form onSubmit={this.submitData}>
<input type="text" name="firstName" onChange={this.inputData}/>
<button type="submit"> Submit</button>
</form>
<Link to="/src/Welcome">Welcome</Link>
</div>
);
}
}
Welcome.js:
import React,{Component} from "react";
import SignUp from './SignUp';
export default class Welcome extends Component {
render(){
return(
<div>
{this.state.firstName}
</div>
);
}
}
"And please give answer if possible then in react-way only not redux or any other library. Because as per Dan Abramov article "Thinking in React" so first I want to try all scope which is available in react only."
Pass the data back to the parent from SignUp component and then pass it as a prop to the Welcome component. The other way is to store the SignUp component state in the App component so that you don't need to pass it back up when you submit.
App.js
import React,{Component} from "react";
import {BrowserRouter as Router, Link, Switch, Route} from "react-router-dom";
import SignUp from './SignUp';
import Welcome from './Welcome';
class App extends Component {
state = {
firstName: ''
}
onSignIn = (value) => {
this.setState({firstName: value});
}
render(){
return(
<Router>
<div>
<Route exact path="/src/Welcome" render={(props) => <Welcome firstName={this.state.firstName} {...props}/>}/>
<Route exact path="/" render={(props) =>{
return(<div><SignUp onSignIn={this.onSignIn} {...props} /></div>);
}}/>
</div>
</Router>
);
}
}
export default App;
SignUp.js
export default class SignUp extends Component {
constructor(props){
super(props);
this.state = {
firstName:''
};
}
inputData = event =>
{
this.setState({
[event.target.name]:event.target.value
});
}
submitData = event =>
{
event.preventDefault();
this.props.onSignIn(this.state.firstName);
}
render(){
return(
<div>
<form onSubmit={this.submitData}>
<input type="text" name="firstName" onChange={this.inputData}/>
<button type="submit"> Submit</button>
</form>
<Link to="/src/Welcome">Welcome</Link>
</div>
);
}
}
Welcome.js
import React,{Component} from "react";
import SignUp from './SignUp';
export default class Welcome extends Component {
render(){
return(
<div>
{this.props.firstName}
</div>
);
}
}
Some useful links:
How to pass data from child component to its parent in ReactJS?
Passing custom props to router component in react-router v4
ReactJS - Lifting state up vs keeping a local state

Categories

Resources