I have an EditProfile functional component that initially loads perfect, but loses state whenever the user refreshes their page with the form open. Instead of pre-filling the inputs with the 'user' state/values, it now sets the inputs as blank, and the 'user' object from const [user, setUser] = useState({}) console.logs as an empty object.
Here is the EditProfile component:
import React, {useEffect, useState} from 'react'
import './EditProfile.css'
export default function EditProfile(props) {
const [user, setUser] = useState({})
let handleChange = (e) => {
setUser({...user, [e.target.name]: e.target.value})
}
let handleSubmit = async () => {
let body = {
_id: user._id,
email: user.email,
username: user.username,
shortDescription: user.shortDescription,
fullDescription: user.fullDescription,
paymentInfo: user.paymentInfo,
publisherAgreement: user.publisherAgreement
}
let options = {
method: 'PUT',
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(body)
}
await fetch('/api/users/editProfile', options)
.then(res => res.json())
.then(data => {
this.props.setUserInState(data)
})
}
useEffect(() => {
(async() => {
setUser(props.user)
})()
},[])
console.log('here is the user: ' + JSON.stringify(user))
return (
<form className='editProfileForm' onSubmit={handleSubmit}>
<input type='hidden' value={user._id}></input>
<input type='hidden' value={user.email}></input>
<div>
<h4>Edit Profile</h4>
<div className="form-group address-update">
<label className="inputUD"><span className="label"><b>Username</b></span></label>
<input type="text" className="form-control" name="username" onChange={handleChange} value={user.username}></input>
</div>
<div className="form-group address-update">
<label className="inputUD"><span className="label"><b>Email</b></span></label>
<input type="text" className="form-control" name="email" onChange={handleChange} value={user.email}></input>
</div>
{user.publisherAgreement &&
<div>
<div className="form-group">
<label className="inputUD"><span className="label"><b>Short Description</b></span></label>
<textarea type="text" className="form-control" name="shortDescription" onChange={handleChange} value={user.shortDescription}></textarea>
</div>
<div className="form-group">
<label className="inputUD"><span className="label"><b>Full Description</b></span></label>
<textarea type="text" className="form-control" name="fullDescription" onChange={handleChange} value={user.fullDescription}></textarea>
</div>
<div className="form-group address-update">
<label className="inputUD"><span className="label"><b>Fake Payment Info</b></span></label>
<input type="text" className="form-control" name="paymentInfo" onChange={handleChange} value={user.paymentInfo}></input>
</div>
</div>
}
<button type="submit" className="btn btn-success">Submit</button>
</div>
</form>
)
}
And here is the App.jsx component where it is called on (I cut out imports to save space):
state = {
user: false,
}
setUserInState = (incomingUserData) => {
console.log('incoming userdata: ' + JSON.stringify(incomingUserData))
this.setState({user: incomingUserData})
}
componentDidMount() {
let token = localStorage.getItem('token')
if (token) {
const payload = JSON.parse(atob(token.split('.')[1]))
if (payload.exp < Date.now() / 1000) {
localStorage.removeItem('token')
token = null
} else {
this.setState({ user: payload.user })
}
}
}
render() {
return (
<div className="App">
<Navbar user={this.state.user} setUserInState={this.setUserInState}/>
<Routes>
<Route path='/ideas/create' element={<NewIdea user={this.state.user} setUserInState={this.setUserInState}/>}/>
<Route path='/users/showProfile' element={<UserProfile user={this.state.user} setUserInState={this.setUserInState}/>}/>
<Route path='/users/editProfile' element={<EditProfile user={this.state.user} setUserInState={this.setUserInState}/>}/>
<Route path='/publishers/becomePublisher' element={<BecomePublisher user={this.state.user} setUserInState={this.setUserInState}/>} />
<Route path='/users/addSubscription'/>
<Route path='/users/removeSubscription'/>
<Route path='/publishers/show/:id' element={<PubProfile user={this.state.user}/>}/>
<Route path='/ideas/show/:id' element={<PubIdeas user={this.state.user}/>}/>
<Route path='/ideas/ideasFeed/:userId' element={<IdeasFeed user={this.state.user}/>}/>
<Route path='/discover/:id' element={<Discover user={this.state.user} setUserInState={this.setUserInState}/>}/>
<Route path='*' element={<Navigate to='/discover/:id' replace />}/>
</Routes>
</div>
)
}
}
The page is accessed via a "Link to" in the Navbar component.
While the form works fine as long as the user doesn't hit refresh, I need the form to be able to handle a refresh and still work.
Any help is much appreciated.
Related
I have an EditProfile functional component that initially loads perfect, but loses state whenever the user refreshes their page with the form open. Instead of pre-filling the inputs with the 'user' state/values, it now sets the inputs as blank, and the 'user' object from const [user, setUser] = useState({}) console.logs as an empty object.
Here is the EditProfile component:
import React, {useEffect, useState} from 'react'
import './EditProfile.css'
export default function EditProfile(props) {
const [user, setUser] = useState({})
let handleChange = (e) => {
setUser({...user, [e.target.name]: e.target.value})
}
let handleSubmit = async () => {
let body = {
_id: user._id,
email: user.email,
username: user.username,
shortDescription: user.shortDescription,
fullDescription: user.fullDescription,
paymentInfo: user.paymentInfo,
publisherAgreement: user.publisherAgreement
}
let options = {
method: 'PUT',
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(body)
}
await fetch('/api/users/editProfile', options)
.then(res => res.json())
.then(data => {
this.props.setUserInState(data)
})
}
useEffect(() => {
(async() => {
setUser(props.user)
})()
},[])
console.log('here is the user: ' + JSON.stringify(user))
return (
<form className='editProfileForm' onSubmit={handleSubmit}>
<input type='hidden' value={user._id}></input>
<input type='hidden' value={user.email}></input>
<div>
<h4>Edit Profile</h4>
<div className="form-group address-update">
<label className="inputUD"><span className="label"><b>Username</b></span></label>
<input type="text" className="form-control" name="username" onChange={handleChange} value={user.username}></input>
</div>
<div className="form-group address-update">
<label className="inputUD"><span className="label"><b>Email</b></span></label>
<input type="text" className="form-control" name="email" onChange={handleChange} value={user.email}></input>
</div>
{user.publisherAgreement &&
<div>
<div className="form-group">
<label className="inputUD"><span className="label"><b>Short Description</b></span></label>
<textarea type="text" className="form-control" name="shortDescription" onChange={handleChange} value={user.shortDescription}></textarea>
</div>
<div className="form-group">
<label className="inputUD"><span className="label"><b>Full Description</b></span></label>
<textarea type="text" className="form-control" name="fullDescription" onChange={handleChange} value={user.fullDescription}></textarea>
</div>
<div className="form-group address-update">
<label className="inputUD"><span className="label"><b>Fake Payment Info</b></span></label>
<input type="text" className="form-control" name="paymentInfo" onChange={handleChange} value={user.paymentInfo}></input>
</div>
</div>
}
<button type="submit" className="btn btn-success">Submit</button>
</div>
</form>
)
}
And here is the App.jsx component where it is called on (I cut out imports to save space):
state = {
user: false,
}
setUserInState = (incomingUserData) => {
console.log('incoming userdata: ' + JSON.stringify(incomingUserData))
this.setState({user: incomingUserData})
}
componentDidMount() {
let token = localStorage.getItem('token')
if (token) {
const payload = JSON.parse(atob(token.split('.')[1]))
if (payload.exp < Date.now() / 1000) {
localStorage.removeItem('token')
token = null
} else {
this.setState({ user: payload.user })
}
}
}
render() {
return (
<div className="App">
<Navbar user={this.state.user} setUserInState={this.setUserInState}/>
<Routes>
<Route path='/ideas/create' element={<NewIdea user={this.state.user} setUserInState={this.setUserInState}/>}/>
<Route path='/users/showProfile' element={<UserProfile user={this.state.user} setUserInState={this.setUserInState}/>}/>
<Route path='/users/editProfile' element={<EditProfile user={this.state.user} setUserInState={this.setUserInState}/>}/>
<Route path='/publishers/becomePublisher' element={<BecomePublisher user={this.state.user} setUserInState={this.setUserInState}/>} />
<Route path='/users/addSubscription'/>
<Route path='/users/removeSubscription'/>
<Route path='/publishers/show/:id' element={<PubProfile user={this.state.user}/>}/>
<Route path='/ideas/show/:id' element={<PubIdeas user={this.state.user}/>}/>
<Route path='/ideas/ideasFeed/:userId' element={<IdeasFeed user={this.state.user}/>}/>
<Route path='/discover/:id' element={<Discover user={this.state.user} setUserInState={this.setUserInState}/>}/>
<Route path='*' element={<Navigate to='/discover/:id' replace />}/>
</Routes>
</div>
)
}
}
The page is accessed via a "Link to" in the Navbar component.
While the form works fine as long as the user doesn't hit refresh, I need the form to be able to handle a refresh and still work.
EDIT/SOLUTION:
I simply passed props.user into the useEffect dependencies array like so:
useEffect(() => {
(async() => {
setUser(props.user)
})()
},[props.user])
The page now sets props into state after a page refresh, just like it does on the first render.
Also, inside my fetch call I switched this.props.setUserInState(data) to just setUser(data).
I am building a login and register app using react and on inspec after hitting Sing up I get the error:
Cannot POST /localhost:8000/register
On the console, the following message is displayed:
POST http://localhost:3001/localhost:8000/register 404 (Not Found)
My app.js looks like this:
import 'bootstrap/dist/css/bootstrap.min.css';
import React from 'react';
import { BrowserRouter,Switch,Route } from "react-router-dom";
import './App.css';
import Home from './components/home_component';
import Nav from './components/nav_component';
import Login from './components/login_component';
import Register from './components/register_component';
function App() {
return (
<BrowserRouter>
<div className="App">
<Nav/>
<div className="auth-wrapper">
<div className="auth-inner">
<Switch>
<Route exact path="/" component={Home}/>
<Route exact path="/login" component={Login}/>
<Route exact path="/register" component={Register}/>
</Switch>
</div>
</div>
</div>
</BrowserRouter>
);
}
export default App;
my register_component.js looks like this:
import React, { Component } from 'react';
import axios from 'axios';
class Register extends Component {
handleSubmit = e => {
e.preventDefault();
const data = {
first_name: this.firstName,
last_name: this.lastName,
email: this.email,
password: this.password,
password_confirm: this.confirmPassword
};
axios.post('http:/localhost:8000/register', data).then(
res =>{
console.log(res);
}
).catch(err =>{
console.log(err);
})
};
render() {
return (
<form onSubmit={this.handleSubmit}>
<h3>Sign Up</h3>
<div className="form-group">
<label>First Name</label>
<input type='text' className='form-control' placeholder='First Name' onChange={e => this.firstName = e.target.value}/>
</div>
<div className="form-group">
<label>Last Name</label>
<input type='text' className='form-control' placeholder='Last Name' onChange={e => this.lastName = e.target.value}/>
</div>
<div className="form-group">
<label>Email</label>
<input type='email' className='form-control' placeholder='Email' onChange={e => this.email = e.target.value}/>
</div>
<div className="form-group">
<label>Password</label>
<input type='password' className='form-control' placeholder='Password'onChange={e => this.password = e.target.value}/>
</div>
<div className="form-group">
<label>Confirm Password</label>
<input type='password' className='form-control' placeholder=' Confirm Password' onChange={e => this.confirmPassword = e.target.value}/>
</div>
<button className='btn btn-primary btn-block'>Sign Up</button>
</form>
);
}
}
export default Register;
You have give the link wrong in your code
axios.post('http:/localhost:8000/register', data).then(
It should be
axios.post('http://localhost:8000/register', data).then(
You are missing a forward slash
I'm am new to React and this is my first project.
I am trying to pass the id (which comes from item.id) of a transaction located in my Summary functional component to my EditTransaction functional component.
It is giving me this error: TypeError: Cannot read property 'props' of undefined
I've tried:
But it does not seem to work either...
App.js
import './App.css';
import {BrowserRouter as Router, Switch, Route, Link, Redirect} from 'react-router-dom';
import Home from "./views/Home";
import Summary from './views/Summary';
import Profile from './views/Profile';
import Groups from './views/Groups';
import About from './views/About';
import Transaction from './views/Transaction';
import Signin from "./components/Signin";
import EditTransaction from "./views/EditTransaction";
import 'bootstrap/dist/css/bootstrap.min.css';
function App() {
return (
<div className="App">
<Router>
<Switch>
<Route exact path="/" component={Home} />
<Route exact path="/Signin" component={Signin} />
<Route exact path="/About" component={About} />
<Route exact path="/Profile" component={Profile} />
<Route exact path="/Groups" component={Groups} />
<Route exact path="/Summary" component={Summary} />
<Route exact path="/Transaction" component={Transaction} />
<Route exact path="/EditTransaction/:id" component={EditTransaction} />
</Switch>
</Router>
</div>
);
}
export default App;
Summary.js
import React, { useEffect, useState } from 'react';
import {NavLink} from 'react-router-dom';
import Button from '#material-ui/core/Button';
import { Redirect } from 'react-router-dom';
import EditTransaction from '../views/EditTransaction';
import SigninNavBar from '../components/SigninNavBar';
function Summary(){
const [error, setError] = useState(null);
const [isLoaded, setIsLoaded] = useState(false);
const [trans, setTrans] = useState([]);
const [signin, setSignin] = useState({signin:localStorage.getItem('token') ? true : false});
const [details, setDetails] = useState({username:"", email:"", password:""});
console.log("Token: " + localStorage.getItem('token'));
const options = {
method: 'GET',
headers: {
'Content-type': 'application/json; charset=UTF-8',
'Accept': 'application/json',
'Authorization': `JWT ${localStorage.getItem('token')}`
}
};
useEffect(() => {
fetch("http://34.94.76.5/api/transactions/get/", options)
.then(response => {
if (response.status !== 200) {
console.log(response.status);
setError(response);
}
response.json().then(data => {
setIsLoaded(true);
setTrans(data);
});
});
}, []);
if (error) {
return (<Redirect to="/Signin" />);
} else if (!isLoaded) {
return <div>Loading...</div>;
} else {
return (
<div>
<SigninNavBar />
<table className="table">
<thead>
<th>ID</th>
<th>Member ID</th>
<th>Created</th>
<th>Category</th>
<th>Description</th>
<th>Amount</th>
</thead>
{trans.map(item => (
<tbody>
<tr>
<td> {item.id} </td>
<td> {item.member_id} </td>
<td> {item.created} </td>
<td> {item.category} </td>
<td> {item.description} </td>
<td> {item.amount} </td>
<td>
<Button variant="contained" color="primary">
<NavLink className="text-white" to={{ pathname:`/EditTransaction/${item.id}`, state:{id: item.id} }}>
Edit
</NavLink>
</Button>
</td>
</tr>
</tbody>
))}
</table>
</div>
);
}
}
export default Summary;
EditTransaction.js
import React, { useEffect, useState } from 'react';
import { Redirect } from 'react-router-dom';
import moment from 'moment';
import SigninNavBar from '../components/SigninNavBar.js';
import Summary from '../views/Summary.js';
var currentDate = moment().format("MM/DD/YYYY HH:mm:ss");
function EditTransaction(props) {
const [error, setError] = useState(null);
const [trans, setTrans] = useState([]);
const [tranUpdated, settranUpdated] = useState({id:0, member_id:'', category:'', description:'', amount:0});
const [isLoaded, setIsLoaded] = useState(false);
const [tran, setTran] = useState([]);
//GET request for specific id
const optionsGET = {
method: 'GET',
headers: {
'Content-type': 'application/json; charset=UTF-8',
'Accept': 'application/json',
'Authorization': `JWT ${localStorage.getItem('token')}`
}
};
useEffect(() => {
fetch("http://34.94.76.5/api/transactions/get/" + this.props.location.state + "/", optionsGET)
.then(response => {
if (response.status !== 200) {
console.log(response.status);
setError(response);
}
response.json().then(data => {
setIsLoaded(true);
setTrans(data);
});
});
}, []);
//PUT request to API for transaction
const optionsPUT = {
method: 'PUT',
headers: {
'Content-type': 'application/json; charset=UTF-8',
'Accept': 'application/json',
'Authorization': `JWT ${localStorage.getItem('token')}`
},
body:JSON.stringify(tranUpdated)
}
const updateTransaction = e => {
e.preventDefault();
fetch("http://34.94.76.5/api/transactions/get/" + this.props.location.state + "/", optionsPUT)
.then((response) => console.log('reponse: ' + response.json()))
.then((message) => console.log('message: ' + message))
}
if (error) {
return (<Redirect to="/Signin" />);
} else{
return (
<div className="wrapper">
<SigninNavBar />
<form>
<h1>Update Transaction</h1>
{trans.map(item => (
<div className="form-horizantal">
<fieldset>
<div className="form-group row">
<label className="col-md-12"><p>{currentDate}</p></label>
</div>
<div className="form-group row">
<label className="col-md-12">
<p>Member ID {item.member_id}</p>
<input type="text" name="member_id" placeholder={item.member_id} onChange={e => settranUpdated({ ...tranUpdated, member_id: e.target.value })} />
</label>
</div>
<div className="form-group row">
<label className="col-md-12">
<p>Transaction ID</p>
<input type="text" name="id" placeholder={item.id} onChange={e => settranUpdated({ ...tranUpdated, id: e.target.value })} />
</label>
</div>
<div className="form-group row">
<label className="col-md-12">
<p>Category</p>
<input type="text" name="category" placeholder={item.category} onChange={e => settranUpdated({ ...tranUpdated, category: e.target.value })} />
</label>
</div>
<div className="form-group row">
<label className="col-md-12">
<p>Description</p>
<input type="text" name="description" placeholder={item.description} onChange={e => settranUpdated({ ...tranUpdated, description: e.target.value })} />
</label>
</div>
<div className="form-group row">
<label className="col-md-12">
<p>Amount</p>
<input type="text" name="amount" placeholder={item.amount} onChange={e => settranUpdated({ ...tranUpdated, amount: e.target.value })} />
</label>
</div>
</fieldset>
<button type="submit" onClick={updateTransaction}>Update</button>
</div>
))}
</form>
</div>
);
}
}
export default EditTransaction;
You shouldn't use the this keyword in a function component
Consider changing this.props.location.state to just props.location.state.id
My App Component is here
import React, { useEffect } from 'react';
import './App.css';
import Navbar from './components/layout/Navbar';
import Landing from './components/layout/Landing';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import Login from './components/auth/Login';
import Register from './components/auth/Register';
import { Provider } from 'react-redux';
import store from './store';
import Alert from './components/layout/Alert';
import setAuthToken from './utils/setAuthToken';
import { loadUser } from './actions/auth';
import Dashboard from './components/dashboard/Dashboard';
import PrivateRoute from './components/routing/PrivateRoute';
import CreateProfile from './components/profile-form/CreateProfile';
import EditProfile from './components/profile-form/EditProfile';
import AddExperience from './components/profile-form/AddExperience';
import AddEducation from './components/profile-form/AddEducation';
if (localStorage.token) {
setAuthToken(localStorage.token);
}
const App = () => {
useEffect(() => {
store.dispatch(loadUser());
}, []);
return (
<Provider store={store}>
<Router>
<>
<Navbar />
<Route exact path='/' component={Landing} />
<section className='container'>
<Alert />
<Switch>
<Route exact path='/login' component={Login} />
<Route exact path='/register' component={Register} />
<PrivateRoute exact path='/dashboard' component={Dashboard} />
<PrivateRoute
exact
path='/create-profile'
component={CreateProfile}
/>
<PrivateRoute
exact
path='/edit-profile'
component={EditProfile}
/>
<PrivateRoute
exact
to='/add-experience'
component={AddExperience}
/>
<PrivateRoute
exact
path='/add-education'
component={AddEducation}
/>
</Switch>
</section>
</>
</Router>
</Provider>
);
};
export default App;
My AddExperience Component is here
import React, { useState } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { addExperience } from '../../actions/profile';
import { Link, withRouter } from 'react-router-dom';
const AddExperience = ({ addExperience, history }) => {
const [formData, setFormData] = useState({
company: '',
title: '',
location: '',
from: '',
to: '',
current: false,
description: '',
});
const [toDateDisabled, toggleDisabled] = useState(false);
const { company, title, location, from, to, current, description } = formData;
const onChange = (e) => {
setFormData({ ...formData, [e.target.name]: e.target.value });
};
return (
<>
<h1 className='large text-primary'>Add An Experience</h1>
<p className='lead'>
<i className='fas fa-code-branch'></i> Add any developer/programming
positions that you have had in the past
</p>
<small>* = required field</small>
<form
className='form'
onSubmit={(e) => {
e.preventDefault();
addExperience(formData, history);
}}
>
<div className='form-group'>
<input
type='text'
placeholder='* Job Title'
name='title'
value={title}
onChange={(e) => onChange(e)}
required
/>
</div>
<div className='form-group'>
<input
type='text'
placeholder='* Company'
name='company'
value={company}
onChange={(e) => onChange(e)}
required
/>
</div>
<div className='form-group'>
<input
type='text'
placeholder='Location'
name='location'
value={location}
onChange={(e) => onChange(e)}
/>
</div>
<div className='form-group'>
<h4>From Date</h4>
<input
type='date'
name='from'
value={from}
onChange={(e) => onChange(e)}
/>
</div>
<div className='form-group'>
<p>
<input
type='checkbox'
name='current'
checked={current}
value={current}
onChange={(e) => {
setFormData({ ...formData, current: !current });
toggleDisabled(!toDateDisabled);
}}
/>{' '}
Current Job
</p>
</div>
<div className='form-group'>
<h4>To Date</h4>
<input
type='date'
name='to'
value={to}
onChange={(e) => onChange(e)}
disabled={toDateDisabled ? 'disable' : ''}
/>
</div>
<div className='form-group'>
<textarea
name='description'
cols='30'
rows='5'
placeholder='Job Description'
value={description}
onChange={(e) => onChange(e)}
></textarea>
</div>
<input type='submit' className='btn btn-primary my-1' />
<a className='btn btn-light my-1' href='dashboard.html'>
Go Back
</a>
</form>
</>
);
};
AddExperience.propTypes = {
addExperience: PropTypes.func.isRequired,
};
export default connect(null, { addExperience })(AddExperience);
Here is my AddEducation Component
import React, { useState, Fragment } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { addEducation } from '../../actions/profile';
import { Link, withRouter } from 'react-router-dom';
const AddEducation = ({ addEducation, history }) => {
const [formData, setFormData] = useState({
school: '',
degree: '',
fieldofstudy: '',
from: '',
to: '',
current: false,
description: '',
});
const [toDateDisabled, toggleDisabled] = useState(false);
const {
school,
degree,
fieldofstudy,
from,
to,
current,
description,
} = formData;
const onChange = (e) => {
setFormData({ ...formData, [e.target.name]: e.target.value });
};
return (
<Fragment>
<h1 className='large text-primary'>Add Your Education</h1>
<p className='lead'>
<i className='fas fa-code-branch'></i> Add any School or bootcamp that
you have attended
</p>
<small>* = required field</small>
<form
className='form'
onSubmit={(e) => {
e.preventDefault();
addEducation(formData, history);
}}
>
<div className='form-group'>
<input
type='text'
placeholder='* School or Bootcamp'
name='school'
value={school}
onChange={(e) => onChange(e)}
required
/>
</div>
<div className='form-group'>
<input
type='text'
placeholder='* Degree or Certificate'
name='degree'
value={degree}
onChange={(e) => onChange(e)}
required
/>
</div>
<div className='form-group'>
<input
type='text'
placeholder='fieldofstudy'
name='fieldofstudy'
value={fieldofstudy}
onChange={(e) => onChange(e)}
/>
</div>
<div className='form-group'>
<h4>From Date</h4>
<input
type='date'
name='from'
value={from}
onChange={(e) => onChange(e)}
/>
</div>
<div className='form-group'>
<p>
<input
type='checkbox'
name='current'
checked={current}
value={current}
onChange={(e) => {
setFormData({ ...formData, current: !current });
toggleDisabled(!toDateDisabled);
}}
/>{' '}
Current Job
</p>
</div>
<div className='form-group'>
<h4>To Date</h4>
<input
type='date'
name='to'
value={to}
onChange={(e) => onChange(e)}
disabled={toDateDisabled ? 'disable' : ''}
/>
</div>
<div className='form-group'>
<textarea
name='description'
cols='30'
rows='5'
placeholder='Programme Description'
value={description}
onChange={(e) => onChange(e)}
></textarea>
</div>
<input type='submit' className='btn btn-primary my-1' />
<a className='btn btn-light my-1' href='dashboard.html'>
Go Back
</a>
</form>
</Fragment>
);
};
AddEducation.propTypes = {
addEducation: PropTypes.func.isRequired,
};
export default connect(null, { addEducation })(AddEducation);
And Lastly here is the DashboardActions Component
import React from 'react';
import { Link } from 'react-router-dom';
const DashboardActions = () => {
return (
<div className='dash-buttons'>
<Link to='/edit-profile' className='btn btn-light'>
<i className='fas fa-user-circle text-primary' /> Edit Profile
</Link>
<Link to='/add-experience' className='btn btn-light'>
<i className='fab fa-black-tie text-primary' /> Add Experience
</Link>
<Link to='/add-education' className='btn btn-light'>
<i className='fas fa-graduation-cap text-primary' /> Add Education
</Link>
</div>
);
};
export default DashboardActions;
The Problem is When i Click on AddExperience it opens correctly with correct url but when i click on AddEducation it Opens the same Add Experience Form but url changed Correctly.
There is a typo here:
<PrivateRoute
exact
to='/add-experience'
component={AddExperience}
/>
The 'to' should be replaced with 'path'
My react app is not redirecting to the dashboard page after submitting a form. I tried using react-router-dom Redirect function but still with no success. I then opt-in for Browser History. push but still no success.
for the latter trial, the URL changes to /dashboard but the component remains on the form page, it doesn't move to dashboard until I reload the page
form field
<form>
<Input
displayValidationErrors={displayValidationErrors("fullname", validators)}
name="fullname"
type="text"
label="Full Name"
onChange={(e) => handleInputChange(e.target.name, e.target.value)}
/>
<Input
displayValidationErrors={displayValidationErrors("password", validators)}
name="password"
type="password"
label="Password"
onChange={(e) => handleInputChange(e.target.name, e.target.value)}
/>
<Input
displayValidationErrors={displayValidationErrors("password2", validators)}
name="password2"
type="password"
label="Confirm Password"
onChange={(e) => handleInputChange(e.target.name, e.target.value)}
/>
<Input
displayValidationErrors={displayValidationErrors("email", validators)}
name="email"
type="email"
label="Email Address"
onChange={(e) => handleInputChange(e.target.name, e.target.value)}
/>
<Input
displayValidationErrors={displayValidationErrors(
"phone_number",
validators
)}
name="phone_number"
type="number"
label="Phone Number"
onChange={(e) => handleInputChange(e.target.name, e.target.value)}
/>
<Input
displayValidationErrors={displayValidationErrors("card_number", validators)}
value={data.card_number}
name="card_number"
type="text"
label="Card Number"
onChange={(e) => handleInputChange(e.target.name, e.target.value)}
/>
<Input
displayValidationErrors={displayValidationErrors("date", validators)}
value={data.date}
name="date"
type="text"
label="Expiry Date"
onChange={(e) => handleInputChange(e.target.name, e.target.value)}
/>
<Input
displayValidationErrors={displayValidationErrors("pin", validators)}
name="pin"
type="password"
label="PIN"
onChange={(e) => handleInputChange(e.target.name, e.target.value)}
/>
<div className="col-lg-12 loginbttm">
<div className=" login-btm login-button">
<Button
handleClick={onSubmit}
type="submit"
className="btn btn-primary"
label="SUBMIT"
disabled={!isFormValid(validators)}
/>
</div>
</div>
</form>;
onSubmit function
const onSubmit = (e) => {
e.preventDefault();
browserHistory.push("/dashboard");
};
Button Component
const Button = ({ type, className, handleClick, label, disabled }) => (
<button
type={type}
className={className}
onClick={handleClick}
disabled={disabled}
>
{label}
</button>
);
My app.js
function App() {
return (
<Router>
<div className="App">
<Switch>
<Route exact path="/dashboard">
<Dashboard />
</Route>
<Route exact path="/">
<Form />
</Route>
</Switch>
</div>
</Router>
);
}
export default App;
I don't see createBrowserHistory or something like <Router history={history}> so I guess you are using the default browser history. In that case you need withRouter to make it work:
import React from "react";
import { withRouter } from "react-router-dom";
function App() {
const onSubmit = (e) => {
e.preventDefault()
this.props.history.push("/personalInfo");
}
...
}
export default withRouter(App);
More about withRouter solution here
More about createBrowserHistory solution here
For functional component with react-router V5, you can also do with hooks:
import { useHistory } from "react-router-dom";
function App() {
let history = useHistory();
const onSubmit = (e) => {
e.preventDefault()
history.push('/dashboard');
}
return (
<Router>
<div className="App">
...
</div>
</Router>
);
}
Take a look at this to know more about useHistory
try using below. hope it'll help
this.props.history.push({
pathname: '/dashboard'
})
Another way of doing it with the function component -
import {withRouter} from "react-router-dom";
function SignIn({history}) {
const submit = (event) => {
event.preventDefault();
history.push("/profile");
}
....
}
export default withRouter(SignIn)