react js authentication best practise - javascript

how can I prevent react routes to be called when a user is not logged in?
Want a single page with a login form be displayed whenn / is called.
every other route should be callable only if a user is logged in.
thanks
index.js
const render = () => {
ReactDOM.render(
<Provider store={store}>
<AppContainer>
<Router history={createHistory}>
<div>
<div className={t.topBar}>
<TopBarHelper/>
</div>
<div className={css.sidebararound}>
</div>
<Route exact path="/" component={Login}/>
<PrivateRoute path="/dashboard" component={Dashboard}/>
....
const fakeAuth = {
isAuthenticated: false,
authenticate(cb) {
this.isAuthenticated = true
setTimeout(cb, 100) // fake async
},
signout(cb) {
this.isAuthenticated = false
setTimeout(cb, 100)
}
}
const AuthButton = withRouter(({ history }) => (
fakeAuth.isAuthenticated ? (
<p>Welcome!</p>
) : (
<p>You are not logged in.</p>
)
))
The login is in a separate file and looks like this:
class Login extends Component {
constructor(props) {
super(props);
this.changeHandler = this.changeHandler.bind(this);
this.state = {
activeSnackbar: false,
snackbarText: '',
redirectToReferrer: false
};
}
componentDidMount() {
this.getData()
};
/**
* Fetches all Data needed for this view
*/
getData() {
console.log(this.props)
};
/**
* Handle Change
* #param field
* #param value
*/
changeHandler(value, {target: {name, type}}) {
this.setState({
[name]: type === 'number' ? parseInt(value, 10) : value,
});
}
/**
* Submit new Ticket Form
* #param event
*/
handleLogin = (event) => {
this.context.router.push('/dashboard');
// axios.post(API_URL + '/dashboard')
// .then((response) => {
// })
// .catch(function (error) {
// console.log(error);
// });
};
render() {
return (
<div>
<div className={css.loginpanel}>
<div className={css.loginpanellogo}>
<img src={logo} width="200px"/>
</div>
<div className={css.loginpanelform}>
<h1><T value="user.login.welcome"/></h1>
<form id="login" method="POST" action="">
<Input type='email' label={<T value='user.login.email'/>} name='email' value={this.state.email} onChange={this.changeHandler}/>
<Input type='password' label={<T value='user.login.password'/>} name='password' value={this.state.password} onChange={this.changeHandler}/>
<br />
<Button icon='save' onClick={this.AuthButton} label={<T value="user.login.signin"/>} raised primary/>
<Button label={<T value="user.login.signup"/>} raised/>
</form>
<br/>
</div>
</div>
</div>
);
}
}
export default connect()(Login);
But I can't call the AuthButton function from Login

It could look like this with react-router-4
<PrivateRoute path="/protected" component={Protected}/>
and
const PrivateRoute = ({ component: Component, ...rest }) => (
<Route {...rest} render={props =>
fakeAuth.isAuthenticated
? <Component {...props}/>
: <Redirect to={{
pathname: '/login',
state: { from: props.location }
}}/>
)}/>
)
The basic gist is that you intercept the transition, check for authentication and redirect accordingly.
See full example here.

you can use two options
you can check whether user is logged in or not on
<Route onChange={requireLogin}></Route>
Or you can check on individual route like
<Route onEnter={requireLogin}/>
/>

Related

React JS: How to Create a preview page from the current view

I've created a React component that takes inputs from other components to display text of various size in a view. Since it is basically a form, what I want to do is pass the current view into another page where I will then post that view to my database as JSON.
Since the state of the input fields are not set in this component, I'm not sure how I would pass them as props to a new view.
This is a condensed version of what my data input component looks like:
INPUTSHOW.JSX
export default class InputShow extends Component {
componentDidMount() {
autosize(this.textarea);
}
render() {
const { node } = this.props;
...
return (
<div className="editor-div" >
{
(node.type === 'buttonA') ?
<textarea
style={hlArea}
ref={a => (this.textarea = a)}
placeholder="type some text"
rows={1}
defaultValue=""
id={node.id} className='editor-input-hl' type="text" onChange={this.props.inputContentHandler} />
:
(node.type === 'buttonB')
?
<textarea
style={subArea}
ref={b => (this.textarea = b)}
placeholder="type some text"
rows={1}
defaultValue=""
id={node.id} className='editor-input-sub' type="text" onChange={this.props.inputContentHandler} />
:
""
}
</div >
)
}
}
This works fine in creating inputs in a current view. I then pass those values to TextAreaField.JSX
export default (props) => {
return (
<>
<button><Link to={{
pathname: '/edit/preview',
text: props.inputsArray
}}>preview</Link></button>
<div className='view'>
{
props.inputsArray.map(
(node, key) => <InputShow key={key} node={node} inputContentHandler={props.inputContentHandler} />
)
}
</div>
</>
)
}
and then finally that is rendered in my Edit.JSX form:
export default class Edit extends React.Component {
constructor(props) {
super(props)
UniqueID.enableUniqueIds(this);
this.state = {
inputs: [],
text: ''
}
}
...
createPage = async () => {
await this.props.postPage(this.state.text)
}
// Handler for listen from button.
buttonCheck = (e) => {
index++;
const node = {
id: this.nextUniqueId() + index,
type: e.target.id,
text: '',
image: true
}
this.setState(
prev => ({
inputs: [...prev.inputs, node]
})
)
console.log(this.state.inputs);
}
inputContentHandler = (e) => {
let newArray = this.state.inputs;
let newNode = newArray.find((node) => {
return (node.id === e.target.id)
})
newNode.text = e.target.value;
this.setState({ inputs: newArray });
console.log(this.state.inputs);
}
render() {
return (
<div>
<InnerHeader />
<div className='some-page-wrapper'>
<div className='row'>
<div className="dash-card-sm">
<br />
<EditButtonContainer buttonCheck={this.buttonCheck} />
<Route path='/edit/form' render={() => (
<TextAreaField
inputsArray={this.state.inputs}
inputContentHandler={this.inputContentHandler}
/>
)}
/>
<Route path='/edit/preview' render={(props) => (
<Preview
inputs={this.state.inputs}
text={this.state.text}
createPage={this.createPage}
/>
)}
/>
<br /> <br />
{/* Button Header */}
</div>
</div>
</div>
</div>
)
}
}
The problem is that I don't know how I should be passing the rendered view to the Preview.jsxcomponent. I'm still new to react (4 months)...Any help in pointing me in the right direction would be appreciated.

React Failed prop type: value without onChange handler

This is my form component:
Form.jsx
import React, { Component } from 'react';
import axios from 'axios';
import { Redirect } from 'react-router-dom';
class Form extends Component {
constructor (props) {
super(props);
this.state = {
formData: {
restaurant: '',
username: '',
email: '',
password: ''
}
};
this.handleUserFormSubmit = this.handleUserFormSubmit.bind(this);
this.handleFormChange = this.handleFormChange.bind(this);
};
componentDidMount() {
this.clearForm();
};
componentWillReceiveProps(nextProps) {
if (this.props.formType !== nextProps.formType) {
this.clearForm();
};
};
clearForm() {
this.setState({
formData: {restaurant: '', username: '', email: '', password: ''}
});
};
handleFormChange(event) {
const obj = this.state.formData;
obj[event.target.name] = event.target.value;
this.setState(obj);
};
handleUserFormSubmit(event) {
event.preventDefault();
const formType = this.props.formType
const data = {
restaurant: this.state.formData.restaurant,
email: this.state.formData.email,
password: this.state.formData.password
};
if (formType === 'register') {
data.username = this.state.formData.username
};
const url = `${process.env.REACT_APP_WEB_SERVICE_URL}/auth/${formType}`;
axios.post(url, data)
.then((res) => {
this.clearForm();
this.props.loginUser(res.data.auth_token);
})
.catch((err) => { console.log(err); });
};
render() {
if (this.props.isAuthenticated) {
return <Redirect to='/' />;
};
return (
<div>
{this.props.formType === 'Login' &&
<h1 className="title is-1">Log In</h1>
}
{this.props.formType === 'Register' &&
<h1 className="title is-1">Register</h1>
}
<hr/><br/>
<form onSubmit={(event) => this.handleUserFormSubmit(event)}>
{this.props.formType === 'Register' &&
<div className="field">
<input
name="restaurant"
className="input is-medium"
type="text"
placeholder="Enter your restaurant name"
required
value={this.state.formData.restaurant}
onChange={this.props.handleFormChange}
/>
</div>
}
<div className="field">
<input
name="username"
className="input is-medium"
type="text"
placeholder="Enter a username"
required
value={this.state.formData.username}
onChange={this.props.handleFormChange}
/>
</div>
<div className="field">
<input
name="email"
className="input is-medium"
type="email"
placeholder="Enter an email address"
required
value={this.state.formData.email}
onChange={this.props.handleFormChange}
/>
</div>
<div className="field">
<input
name="password"
className="input is-medium"
type="password"
placeholder="Enter a password"
required
value={this.state.formData.password}
onChange={this.props.handleFormChange}
/>
</div>
<input
type="submit"
className="button is-primary is-medium is-fullwidth"
value="Submit"
/>
</form>
</div>
)
};
};
export default Form;
and this is my app component:
App.jsx
import React, { Component } from 'react';
import { Route, Switch } from 'react-router-dom';
import axios from 'axios';
import UsersList from './components/UsersList';
import About from './components/About';
import NavBar from './components/NavBar';
import Form from './components/Form';
import Logout from './components/Logout';
import UserStatus from './components/UserStatus';
class App extends Component {
constructor() {
super();
this.state = {
users: [],
title: 'Test.io',
isAuthenticated: false,
};
this.logoutUser = this.logoutUser.bind(this);
this.loginUser = this.loginUser.bind(this);
};
componentWillMount() {
if (window.localStorage.getItem('authToken')) {
this.setState({ isAuthenticated: true });
};
};
componentDidMount() {
this.getUsers();
};
getUsers() {
axios.get(`${process.env.REACT_APP_WEB_SERVICE_URL}/users`)
.then((res) => { this.setState({ users: res.data.data.users }); })
.catch((err) => { });
};
logoutUser() {
window.localStorage.clear();
this.setState({ isAuthenticated: false });
};
loginUser(token) {
window.localStorage.setItem('authToken', token);
this.setState({ isAuthenticated: true });
this.getUsers();
};
render() {
return (
<div>
<NavBar
title={this.state.title}
isAuthenticated={this.state.isAuthenticated}
/>
<section className="section">
<div className="container">
<div className="columns">
<div className="column is-half">
<br/>
<Switch>
<Route exact path='/' render={() => (
<UsersList
users={this.state.users}
/>
)} />
<Route exact path='/about' component={About}/>
<Route exact path='/register' render={() => (
<Form
formType={'Register'}
isAuthenticated={this.state.isAuthenticated}
loginUser={this.loginUser}
/>
)} />
<Route exact path='/login' render={() => (
<Form
formType={'Login'}
isAuthenticated={this.state.isAuthenticated}
loginUser={this.loginUser}
/>
)} />
<Route exact path='/logout' render={() => (
<Logout
logoutUser={this.logoutUser}
isAuthenticated={this.state.isAuthenticated}
/>
)} />
<Route exact path='/status' render={() => (
<UserStatus
isAuthenticated={this.state.isAuthenticated}
/>
)} />
</Switch>
</div>
</div>
</div>
</section>
</div>
)
}
};
export default App;
This is the error console is showing:
index.js:1446 Warning: Failed prop type: You provided a `value` prop to a form field without an `onChange` handler. This will render a read-only field. If the field should be mutable use `defaultValue`. Otherwise, set either `onChange` or `readOnly`.
in input (at Form.jsx:72)
in div (at Form.jsx:71)
in form (at Form.jsx:69)
in div (at Form.jsx:61)
in Form (at App.jsx:66)
in Route (at App.jsx:65)
in Switch (at App.jsx:58)
in div (at App.jsx:56)
in div (at App.jsx:55)
in div (at App.jsx:54)
in section (at App.jsx:53)
in div (at App.jsx:48)
in App (at src/index.js:9)
in Router (created by BrowserRouter)
in BrowserRouter (at src/index.js:8)
I don't get it, though, because form change is being handled at <input> in the code above, like so:
onChange={this.props.handleFormChange}
so what am I missing? forms are not even accepting inputs.
You have fundamentally misunderstood the props concept in React components. I will try to explain it with a more simplified version of your app. Lets take the form example.
class Form extends Component {
handleFormChange(){
console.log("This is the form change function inside -Form-");
}
render(){
return(
<div>
<input
name="email"
type="text"
value={this.state.email}
onChange={this.handleFormChange} // Focus point 1 - Calls local function
/>
<input
name="username"
type="text"
value={this.state.username}
onChange={this.props.handleFormChange} // Focus point 2 - Calls function passed down via props
/>
</div>
);
}
}
class App extends Component {
handleFormChange(){
console.log("This is the form change function inside -App-");
}
render(){
return <Form handleFormChange={this.handleFormChange} />
}
}
As you can see the App is going to render the Form component. Look at Focus point 1 and 2. In the first focus point its trying to access the local 'handleFormChange' function. And the 2nd one tries to call whatever the function that is provided by the parent via props.
So what happened is that you are telling the 'Form' component to access the handleFormChange function which should have been provided by the parent as a "prop" i.e this.props.handleFormChange. So when the component is mounted React tries to bind this.props.handleFormChange to the onChange event of the input.
But in your instance, the 'handleFormChange' prop in the component is not provided. hence this.props.handleFormChange will be undefined resulting in that warning.
So to wire up any handlers that are within the Form component they should not be linked with 'this.props'. Whatever handlers that are accessed via props should be provided by the parent when initializing the component.
Its because you are not passing any prop named as handleFormChange from App.jsx to the Form component.
Instead, it's in your own Form component.
So, just try this onChange={this.handleFormChange}

how to Stop rerendering of entire component onChange event on input text field in reactJs

I m new to reactJs and i m creating user Authentication functionality. I have two components one is header which has navbar and it contains react-router routers and the other is login component which has two input fields ... The problem with login component is when i start typing in input field it loses focus after each character typed i know it is rerendering the whole component but i don't know how to solve this problem
header.js
changeName = (e) => {
this.setState({name : e.target.value})
}
changePass = (e) => {
this.setState({password:e.target.value})
}
login = () => {
var name = this.state.name;
var password = this.state.password
var mysession;
$.ajax({
url : 'http://localhost:4000/login',
type : "POST",
data : {username:name,password:password},
success : function(data){
if(data == true){
this.setState({sessionFlag:true})
$('#home')[0].click();
}
else {
this.setState({sessionFlag:false})
}
}.bind(this)
})
}
render(){
const {name,password} = this.state;
return (
<Router>
<div>
<Route path="/login" exact component={()=><Login
onClickHandle={this.login.bind(this)}
onChangeName={this.changeName.bind(this)}
onChangePass={this.changePass.bind(this)}
name={name}
password = {password} />} />
</div>
</Router>
)
}
login.js
render(){
return (
<form className="form-horizontal" method ="post">
<input
type="text"
onChange={this.props.onChangeName}
value={this.props.name}/>
<input type="text"
onChange={this.props.onChangePass}
value={this.props.password} />
<input type="button"
value="Login"
onClick={this.props.onClickHandle} />
</form>
)
}
The main issue is the manner in which you are specifying your Login component:
<Route
path="/login"
exact
component={() => (
<Login
onChangeName={this.changeName.bind(this)}
onChangePass={this.changePass.bind(this)}
name={this.state.name}
password={this.state.password}
/>
)}
/>
Using this syntax causes the child of the Route to look like a brand-new type of component with each rendering (since it will be a new arrow function instance each time) so the previous Login component will be completely unmounted and the new one mounted.
From https://reactrouter.com/web/api/Route/component:
When you use component (instead of render or children, below) the router uses React.createElement to create a new React element from the given component. That means if you provide an inline function to the component prop, you would create a new component every render. This results in the existing component unmounting and the new component mounting instead of just updating the existing component. When using an inline function for inline rendering, use the render or the children prop (below).
Here is an example using the render-func approach:
Header.js
import React from "react";
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
import Login from "./Login";
class Header extends React.Component {
constructor(props) {
super(props);
this.state = { name: "", password: "" };
this.changeName = this.changeName.bind(this);
this.changePass = this.changePass.bind(this);
}
changeName = (e) => {
this.setState({ name: e.target.value });
};
changePass = (e) => {
this.setState({ password: e.target.value });
};
render() {
return (
<Router>
<div>
<div>
<Link to="/login">Login</Link>
</div>
<Route
path="/login"
exact
render={() => (
<Login
onChangeName={this.changeName}
onChangePass={this.changePass}
name={this.state.name}
password={this.state.password}
/>
)}
/>
</div>
</Router>
);
}
}
export default Header;

React Router is not redirecting on Login and on Logout

I've just few days of knowledge of React Router and I'm trying to let it work but evidently I'm missing something. I've followed the tutorial on the docs but I'm not having any luck.
This are my classes:
App.js
constructor(props) {
super(props);
this.state = {
page: 'login'
}
this.handleOnLogout = this.handleOnLogout.bind(this);
}
handleOnLogout(callback) {
UserDAO.logout().then(() => {
callback();
}).catch(error => console.log(error));
}
render() {
return (
<Router>
<div>
<Navbar onLogout={this.handleOnLogout}/>
<Switch>
<Route path="/login" component={LoginPage} />
<PrivateRoute path="/" component={Dashboard}/>
</Switch>
</div>
</Router>
);
}
function PrivateRoute({ component: Component, ...rest }) {
return (
<Route
{...rest}
render={props =>
UserDAO.isLoggedIn ? (
<Component {...props}/>
) : (
<Redirect
to={{
pathname: "/login",
state: { from: props.location }
}}
/>
)
}
/>
)
}
LoginPage.js
handleOnLogin(email, password, positive, negative) {
let self = this;
UserDAO.login(email, password).then(user => {
console.log("Successfully logged in as user #" + user.id);
positive("Successfully logged in, you'll be soon redirected to the homepage.");
setTimeout(() => { self.setState({redirectToReferrer: true }) }, 500 );
}).catch( error => {
console.log("Error logging in with email/password auth: " + error);
negative("Error logging in with email/password auth: " + error);
});
}
render() {
const { from } = this.props.location.state || { from: { pathname: "/" } };
const { redirectToReferrer } = this.state;
if (UserDAO.isLoggedIn || redirectToReferrer) return <Redirect to={from} />;
return (
<div className="login-page">
<div className="container d-flex align-items-center">
<div className="row d-flex justify-content-center">
<div className="col-12 col-lg-6">
<LoginForm onLogin={this.handleOnLogin}
onForgotPassword={() => { this.setState({ showForgotPasswordModal: true }); } }
onResendActivation={() => { this.setState({ showResendActivationModal: true }); } }/>
</div>
</div>
</div>
<ResendActivationModal show={this.state.showResendActivationModal} enabled onClose={this.closeResendActivationModal}/>
<ForgotPasswordModal show={this.state.showForgotPasswordModal} enabled onClose={this.closeForgotPasswordModal}/>
</div>
);
}
Navbar.js
const Navbar = withRouter(
({ history, onLogout }) => {
return (
<nav className="navbar navbar-dark fixed-top bg-dark flex-md-nowrap p-0 shadow">
<a className="navbar-brand col-sm-3 col-md-2 mr-0" href="#">MANA</a>
<ul className="navbar-nav px-3">
{UserDAO.isLoggedIn &&
<li className="nav-item text-nowrap">
<LinkButton className="nav-link" onClick={() => {
onLogout(() => { history.push("/"); console.log(history); })
}} href="#">Log out</LinkButton>
</li>}
</ul>
</nav>
);
}
);
UserDAO maintain the auth variables and its methods return promises for login and logout (I'm using MongoDB Stitch Browser SDK).
Login and Logout methods are working: after login if I refresh the page it loads the private route, after clock on logout -> refresh -> then I get the login page. I want it to do this without manual refresh.
I want to do following a good design guideline, but it's almost identical to the official tutorial but it doesn't work.
Edited
I added some logging before the <Redirect/> in the LoginPage for the comment of #c-chavez and it get to me this:
Don't know why it prints twice.
Try changing this:
<PrivateRoute path="/" component={Dashboard}/>
Into:
<PrivateRoute path="/dashboard" component={Dashboard}/>
And, you can Redirect like this:
if (UserDAO.isLoggedIn || redirectToReferrer) return <Redirect to='dashboard' />;
For this question:
Don't know why it prints twice.
Thing is, when you do this:
const { from } = this.props.location.state || { from: { pathname: "/" } };
for sure this.props.location.state exists. It should be your current path, which is '/login' I imagine. Since it will try to redirect to '/login' again after it logs you in (which is handled by your router), you render the same page, and thus render the second message with both variables set to false.
I wouldn't trust much on that DAO you have to handle the state of the user in the app. I would use either cookies, session, redux, or something that does this for sure.
That was all a my mistake:
in my UserDAO library I exported a variable in this way:
export var isLoggedIn = client.auth.isLoggedIn
so it return always the same value of the variable that was when the library was imported.
But I want it to be updated every time, so I changed it to:
export function isLoggedIn() {
return client.auth.isLoggedIn;
}
And it works!
Thank you all.
Fell free to answer again and correct everything in my design way.

React-Router - Pass Method to Child Component

I have a button nested within a component called "Create" that has to trigger a change in state that changes the state in app.js and renders a fresh view.
I can't seem to pass the method changeHPage from app.js to the Create component. I am using React-Router and normally I would simply write <App changeHPage={this.changePage}> to pass the method to its child component and call it using this.props.changeHpage but I can't pass props via this method when using React Router.
Any help on how to pass a method to a child component using React Router would be much appreciated. My code can be found below.
app.js:
/* STRICT MODE: See `../../server.js` */
'use strict';
/* GLOBAL REACT REQUIRES */
// React.js
const React = require('react');
// React-DOM for HTML rendering
const ReactDOM = require('react-dom');
// React router for dynamic pathing. Has several component features that need to be required to use.
const ReactRouter = require('react-router');
// 4 components pulled from ReactRouter:
const Router = ReactRouter.Router;
const Route = ReactRouter.Route;
const Navigation = ReactRouter.Navigation;
const Link = ReactRouter.Link;
const browserHistory = ReactRouter.browserHistory;
/* Relative paths to external components */
const auth = require('./helpers/auth.js');
const requireAuth = require('./helpers/requireauth.js');
const About = require('./components/about.js');
const Login = require('./components/login.js');
const Logout = require('./components/logout.js');
const Signup = require('./components/signup.js');
const Header = require('./components/header.js');
const Create = require('./components/create.js');
const NotFound = require('./components/notfound.js');
const Veri = require('./components/veri.js');
/* React App Creation */
const App = React.createClass({
// Declares the initial state when app is loaded
getInitialState : function() {
return {
loggedIn: auth.loggedIn(),
change: true,
phoneNumber: {}
}
},
// Updates state when login is trigger
updateAuth : function(loggedIn) {
this.setState({
loggedIn: loggedIn
})
},
changeHPage: function() {
this.state.change = !this.state.change;
this.setState({
change: !this.state.change
});
console.log("changePage On HomePage Pressed");
this.context.router.push('/')
},
// Login even triggered and sent to back-end
componentWillMount : function() {
auth.onChange = this.updateAuth
auth.login()
},
addNumber: function(phonenumber){
this.state.phonenumber = phonenumber
this.setState()
},
// Renders App and all of its children
render : function() {
<div className="Detail">
{this.props.children && React.cloneElement(this.props.children, {
changeHPage: this.changeHPage
})}
</div>
var firstView;
{if(this.state.change) {
firstView = <div>
<div className="row">
<Veri> This is a child of Veri </Veri>
<Header details="Hi, I'm Plantee"/>
<section className="col s12">
<ul>
{this.state.loggedIn ? (
<div>
<li><Link to="/logout">Log out</Link> </li>
<li><Link to="/create">Create Your Plantee</Link></li>
{/*<Create> <Veri/> </Create>*/}
</div>
) : (
<div>
<li><Link to="/login">Log In</Link></li>
<li><Link to="/signup">Sign up</Link></li>
</div>
)}
<li><Link to="/about">About</Link></li>
</ul>
{this.props.children || <p>You are {!this.state.loggedIn && 'not'} logged in.</p>}
</section>
</div> </div>
} else {
firstView= <div>'Hello'</div>
}
return React.cloneElement(
firstView,
{switch: this.changeHPage}
)
}}
})
/* React router initialization */
var routes = (
<Router history={browserHistory}>
<Route path="/" component={App} >
<Route path="header" component={Header} />
<Route path="login" component={Login} />
<Route path="logout" component={Logout} />
<Route path="create" component={Create} change={App.changeHPage} />
<Route path="signup" component={Signup} />
<Route path="about" component={About} />
<Route path="very" component={Veri} />
</Route>
<Route path="*" component={NotFound} />
</Router>
)
ReactDOM.render(routes, document.querySelector('#container'))
create.js:
const React = require('react');
const ReactDOM = require('react-dom');
const auth = require('../helpers/auth')
const Veri = require('./veri.js');
const App = require('../app.js');
const ReactRouter = require('react-router');
// 4 components pulled from ReactRouter:
const Router = ReactRouter.Router;
const Route = ReactRouter.Route;
const Navigation = ReactRouter.Navigation;
const Link = ReactRouter.Link;
const browserHistory = ReactRouter.browserHistory;
const Create = React.createClass({
getInitialState: function(){
return {checked: false}
},
handleClick: function(event) {
event.preventDefault();
this.setState({checked: !this.state.checked})
let phonenumber = {
phonenumber: this.refs.phonenumber.value
}
},
showVerification : function(event) {
event.preventDefault();
},
remove(e) {
e.preventDefault();
console.log(this.props);
},
render : function(){
var msg;
{if(this.state.checked) {
msg = <div><Veri text={'Your verification code is '} code={'code'}/> <form className="gotIt" onSubmit={this.props.changeHpage} >
<input type="Submit" value="Got It" />
</form> </div>
}
else {
msg = <Veri details={''}/>
}}
return (
<div>
<h1>Create Your Plantee</h1>
<h2>Please Enter Your Phone Number</h2>
<p>You will recieve a phone call in order to verify that you are capable of raising a plantee</p>
<form className="telephoneNumber" onSubmit={this.handleClick}>
<input id="phonenumber" ref="phonenumber" type="tel" />
<input type="Submit" />
</form>
<div> {msg} </div>
<h3>{this.props.children}</h3>
</div>
)
}
})
module.exports = Create;
Please see the following github issue:
https://github.com/reactjs/react-router/issues/1857
this is directly taken from: ryanflorence
Usually if you're passing props across route boundaries your parent route knows exactly what it's rendering:
<Route path="/inbox" component={Inbox}>
<Route path=":messageId" component={Message}/>
<IndexRoute component={InboxStats}/>
</Route>
const Inbox = React.createClass({
render() {
return (
<div>
{/* this is only ever `Message`, except the weird case
of `InboxStats` which doesn't need the prop */}
{React.cloneElement(this.props.children, {
onDelete: this.handleMessageDelete
})}
</div>
)
}
})
Instead, use a componentless route and just do "normal" React stuff.
<Route path="/inbox" component={Inbox}>
{/* no more `Message` */}
<Route path=":messageId"/>
</Route>
const Inbox = React.createClass({
render() {
const { messageId } = this.props.params
return (
<div>
{messageId ? (
<Message onDelete={this.handleMessageDelete}/>
) : (
<InboxStats/>
)}
</div>
)
}
})
cloneElement is not bad practice on its own, but it can often be an indicator that there's a bit more straightforward way of doing something.

Categories