Parameter Route in ReactJS not show UI Component - javascript

I use Laravel as backend and ReactJS as frontend. In ReactJS, create Routes.
In Laravel, create Api. When I parse the Parameter from ReactJS to Laravel, First time okay. After I reload these page, show Json Only
I tried Parameter Route like this "/:id" and work. But for multiple Objects it did not solve. It work for only one Object.
App.js
import React, { Component } from 'react'
import ReactDOM from 'react-dom'
import { BrowserRouter, Route, Switch, browserHistory,IndexRoute } from 'react-router-dom'
import NewApp from './NewApp'
import AppList from './AppList'
import NAVBAR from './NAVBAR'
import Container from './Container'
import MainNavigation from './MainNavigation'
import AppSettingList from './AppSettingList'
import UpdateApp from './UpdateApp'
import {withRouter} from 'react-router';
class App extends Component {
render () {
console.log(window.location.pathname);
return (
<BrowserRouter>
<div>
{/* <Header /> */}
<NAVBAR />
<MainNavigation />
<Switch>
<Route exact path='/' component={withRouter(Container)} />
<Route exact path='/dashboard/' component={withRouter(Container)} />
<Route exact path='/app/' component={withRouter(AppList)} />
<Route exact path='/app/:id' component={withRouter(UpdateApp)} />
<Route exact path='/appsetting/' component={withRouter(AppSettingList)} />
<Route exact path='/app/create' component={withRouter(NewApp)} />
</Switch>
</div>
</BrowserRouter>
)
}
}
ReactDOM.render(<App />, document.getElementById('app'))
UpdateApp.js
import axios from 'axios'
import React, { Component } from 'react'
import NiftySuccessModal from './alerts/NiftySuccessModal'
class UpdateApp extends Component {
constructor (props) {
super(props)
this.state = {
name: '',
description: '',
errors: [],
apps : [],
id : 0,
loading : false,
successModal : false
};
// binding
this.handleSubmit = this.handleSubmit.bind(this);
this.handleChange = this.handleChange.bind(this);
this.hasErrorFor = this.hasErrorFor.bind(this);
this.renderErrorFor = this.renderErrorFor.bind(this);
this.showSuccessModal = this.showSuccessModal.bind(this);
this.getApp = this.getApp.bind(this);
this.gotoApp = this.gotoApp.bind(this);
}
getApp(appId){
axios.get(`/app/${appId}`).then(response => { // return value
this.setState({
apps: response.data.apps,
name : response.data.apps.name,
id : response.data.apps.id
});
console.log(response.data.apps);
});
}
componentDidMount () {
const appId = this.props.match.params.id;
this.getApp(appId);
}
gotoApp(){
this.props.history.push('/app');
}
handleChange(e){
this.setState({
name: e.target.value
});
}
showSuccessModal(e){
this.setState({
successModal : true
});
setTimeout(() => {
this.setState({
successModal: false
})
}, 10000);
}
hasErrorFor (field) {
return !!this.state.errors[field]
}
renderErrorFor (field) {
if (this.hasErrorFor(field)) {
return (
<span className='invalid-feedback'>
<strong>{this.state.errors[field][0]}</strong>
</span>
)
}
}
handleSubmit(e){
e.preventDefault();
const params = {
id : this.state.id,
name: this.state.name
}
console.log('Update');
axios
.post('/app/update', params)
.then(response => {
console.log('Success');
})
.catch(error => {
console.log('Error');
this.setState({
errors: error.response.data.errors
});
})
}
render () {
return (
<div id="content-container">
<div id="page-head">
<div className={"pad-all text-center"}>
<h3>Welcome back to the Dashboard.</h3>
<p>Scroll down to see quick links and overviews of your Server, To do list, Order status or get some Help using Nifty.</p>
</div>
</div>
<div id="page-content">
<div className={"row"}>
<div className={"col-md-1"}></div>
<div className={"col-lg-9"}>
<NiftySuccessModal show={this.state.successModal} > Successfully Updated! </NiftySuccessModal>
<div className={"panel"}>
<div className={"panel-heading"}>
<h3 className={"panel-title"}>App </h3>
</div>
<form className={"panel-body form-horizontal form-padding"} onSubmit={this.handleSubmit}>
<div className={"form-group"}>
<label className={"col-md-3 control-label"} >App Name</label>
<div className={"col-md-9"}>
<input type="text"
name='name'
id='name'
onChange={this.handleChange}
value={this.state.name}
className={"form-control"}
maxLength="255"
placeholder="App Name..."
required className={"form-control"} placeholder="Text" />
<small className={"help-block"}>This is a help text</small>
</div>
</div>
<div className={"form-group demo-nifty-btn col-md-3"}>
<input type="submit" onClick={this.showSuccessModal} value="Update" className={"form-control btn btn-primary"} />
</div>
</form>
</div>
</div>
</div>
</div>{/* End <!--Page content--> */}
</div> // End <!--CONTENT CONTAINER-->
)
}
}
export default UpdateApp
![Before Reload]: (https://i.imgur.com/rWqFo9Y.png)
![After Reload]: (https://i.imgur.com/maR3x1S.png)

Now Solved! using difference route name and Query Strings with React Router. Page Reload also okay. Thanks.
that is not working
<Route path='/app' component={withRouter(AppList)} />
<Route path='/app/:id' component={withRouter(UpdateApp)} />
working with Query String
<Route path='/updateapp' component={withRouter(UpdateApp)} />

Related

reactjs preventDefault() is not preventing the page reload on form submit

EDIT: Events are not working at all, the onSubmit and onChange functions are not being called. I have another reactapp with similar form and onChange and onSubmit works OK there.
I have a form I dont want the page to refresh when I click on submit. I tried using preventDefault() but I didnt work. Even onChange is printing anything on console. This form is not on page, I am using React Router to point to='/new' and component={NewPost} (NewPost is in ./components/posts/form)
./components/posts/form.js:
import React, { Component } from "react";
import { connect } from "react-redux";
class NewPost extends Component {
state = {
title: "",
body: "",
status: 0,
};
onSubmit = (e) => {
e.preventDefault();
const post = e;
console.log(post);
};
onChange = (e) => {
console.log(e.target.value);
this.setState({
[e.target.name]: e.target.value,
});
};
render() {
const { title, body, status } = this.state;
return (
<div className="card card-body mt-4 mb-4">
<h2>New Post</h2>
<form onSubmit={this.onSubmit}>
<div className="form-group">
<label>Title</label>
<input
type="text"
name="title"
value={title}
onChange={this.onChange}
className="form-control"
/>
</div>
<div className="form-group">
<label>Content</label>
<textarea
type="text"
name="body"
rows="15"
value={body}
onChange={this.onChange}
className="form-control"
/>
</div>
<div className="form-group">
<button className="btn btn-primary" type="submit">
Submit
</button>
</div>
</form>
</div>
);
}
}
export default NewPost;
App.js:
import React from "react";
import NavBar from "./components/layout/navbar";
import store from "./store";
import { Provider } from "react-redux";
import Dashboard from "./components/posts/dashboard";
import NewPost from "./components/posts/form";
import {
HashRouter as Router,
Route,
Switch,
Redirect,
} from "react-router-dom";
class App extends React.Component {
render() {
return (
<Provider store={store}>
<Router>
<React.Fragment>
<div className="container">
<NavBar />
<Switch>
<Route exact path="/" component={Dashboard}></Route>
<Route exact path="/new" component={NewPost}></Route>
</Switch>
</div>
</React.Fragment>
</Router>
</Provider>
);
}
}
export default App;
Issue is not related to code. I created new react application and moved all my code now everything is working fine.

React Protected Route does not show component

I'm just beginner for React. Now, I'm trying to protect route and there's no error and nothing on the console that could explain what's wrong why it doesn't show the component as it should be.
Here are my codes.
//App.js
import React, { Component } from 'react';
import { BrowserRouter, Route, Switch } from 'react-router-dom';
import Login from './Login';
import Dashboard from './Dashboard';
import { ProtectedRoute } from './ProtectedRoute';
import Logout from './Logout';
export default class App extends Component {
render() {
return (
<BrowserRouter>
<Switch>
<Route exact path="/" component={Login} />
<ProtectedRoute path="/dashboard" component={Dashboard} />
<Route path="/logout" component={Logout} />
<Route path="*" component={() => "404 NOT FOUND"} />
</Switch>
</BrowserRouter>
)
}
}
//ProtectedRoute.js
import React from 'react';
import { Route, Redirect } from 'react-router-dom';
import auth from './auth';
export const ProtectedRoute = ({ component: Component, ...rest }) => {
return(
<Route
{...rest}
render = {props => {
auth.isAuthenticated().then(resp =>
resp === true ? (<Component {...props} {...rest} />) : (
<Redirect to={
{
pathname: "/",
state: {
from: props.location
}
}
} />
)
).catch(error => {
alert(error);
});
}}
/>
);
};
...
//auth.js
import axios from 'axios';
axios.defaults.withCredentials = true;
class Auth {
constructor(){
this.host = 'http://' + window.location.hostname + ':5000';
}
isAuthenticated(){
return new Promise((resolve, reject) => {
axios.get(`${this.host}/getsignin`).then(resp => {
console.log('resp.data from isAuthenticated() : '+resp.data);
resolve(resp.data)
}).catch(error => {
reject(error);
});
});
}
login(username, password){
return new Promise((resolve, reject) => {
axios.post(`${this.host}/signin`, {
user: username,
password: password
}).then(resp => {
let rs = JSON.stringify(resp.data);
if(rs === "1"){
resolve(true);
}else{
resolve(false);
}
}).catch(error => {
reject(error);
});
});
}
}
export default new Auth();
...
//Login.js
import React, { Component } from 'react';
import $ from 'jquery';
import { WaveLoading } from 'react-loadingg';
import auth from './apis/auth';
import { Redirect } from 'react-router';
export default class Login extends Component {
constructor(props){
super(props);
this.state = {
redirect: false,
loading: true
}
this.onSubmit = this.onSubmit.bind(this);
}
onSubmit(){
auth.login($('#txtUser').val(), $('#txtPass').val())
.then(resp => {
this.setState({
redirect : resp
});
}).catch(error => {
alert(error);
});
}
showLogin(){
return(
<div className="hold-transition login-page">
<div className="login-box">
<div className="login-logo">
<b>KVC Computer</b>
</div>
<div className="card">
<div className="card-body login-card-body">
<p className="login-box-msg">Sign in</p>
<div className="input-group mb-3">
<input type="text" className="form-control" placeholder="Username" name="txtUser" id="txtUser" />
<div className="input-group-append">
<div className="input-group-text">
<span className="fas fa-user" />
</div>
</div>
</div>
<div className="input-group mb-3">
<input type="password" className="form-control" placeholder="Password" name="txtPass" id="txtPass" />
<div className="input-group-append">
<div className="input-group-text">
<span className="fas fa-lock" />
</div>
</div>
</div>
<div className="row">
<div className="col-8">
<div className="icheck-primary">
<input type="checkbox" id="chkRem" name="chkRem" />
<label htmlFor="remember">
Remember Me
</label>
</div>
</div>
<div className="col-4">
<button className="btn btn-primary btn-block" name="btnSignin" id="btnSignin" onClick={this.onSubmit}>Sign In</button>
</div>
</div>
<div className="social-auth-links text-center mb-3">
<p>- OR -</p>
</div>
<p className="mb-1">
forgot your password
</p>
</div>
</div>
</div>
</div>
)
}
componentDidMount(){
this.setState({ loading : false });
auth.isAuthenticated().then(res => {
this.setState({ redirect : res });
console.log('isAuthenticat : '+res);
})
}
render() {
if(this.state.redirect){
return <Redirect to="/dashboard" />;
}
return (
this.state.loading ? <WaveLoading /> : this.showLogin()
)
}
}
Login.js -> If user already login then redirect to dashboard
//Dashboard.js
import React, { Component } from 'react';
export default class Dashboard extends Component {
constructor(props){
super(props);
console.log('constructor');
}
componentDidMount(){
console.log('componentDidMount');
}
onRender = () => {
return (
<div>
<h1>This is dashboard!!</h1>
</div>
);
}
render() {
console.log('render');
return (
this.onRender()
)
}
}
After user has logged in Auth.isAuthenticated() return true and ProtectedRoute should return Component to App (Dashboard). It shows nothing on the browser but the url is http://xxx.xxx.xxx.xxx/dashboard
I have no idea why is that happend and how to solve this. Should I change some code?
I'm stuck on this for days.
Thanks

Routing in ReactJS. URL is displayed but component is not rendered

I have the following piece of code in my parent component:
class App extends Component {
render() {
return(
<Router>
<div>
<Route exact path='/' component={Main} />
<Route path="/login" component={Login} />
</div>
</Router>
);
}}
And this in Main component:
import React, { Component } from "react";
import {BrowserRouter as Router, Route, Link } from 'react-router-dom'
class Main extends Component {
render() {
return (
<Router>
<section className="section main">
<div className="container">
<div className="main-titles-container">
<div className="main-titles">
<div className="yellow-square"></div>
<h1>Title</h1>
<p>
Introduction
</p>
<div className="button-container">
<Link to='/login' className="btn select bg-yellow" id="buyer">Next</Link>
</div>
</div>
</div>
</div>
</section>
</Router>
);
}
}
export default Main;
Login:
import React, { Component } from 'react';
class Login extends React.Component {
constructor(props) {
super(props);
this.state = {
email: "",
cellphone: ""
}
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(e) {
const target = e.target;
this.setState({
[target.name]: target.value
});
}
handleSubmit(e) {
e.preventDefault();
console.log(this.state);
}
render() {
return (
<section className="section">
<div className="container center center-xy">
<h1 className="title center-self">Title</h1>
<h1 className="title center-self">Log in</h1>
<div className="form-container">
<form onSubmit={this.handleSubmit}>
<label htmlFor="email">Email</label>
<input type="text" name="email" id="email" onChange={this.handleChange} defaultValue="" required/>
<label htmlFor="cellphone">Cell phone</label>
<input type="text" name="cellphone" id="cellphone" defaultValue="" onChange={this.handleChange} required/>
<button className="bg-yellow center-self" type="submit">Ok</button>
</form>
</div>
</div>
</section>
);
}
}
export default Login;
On click I want to be redirected to Login page, but the problem is that when i click on that 'button' the URL is changed to '/login', but the corresponding component isn't rendered. However, if I refresh the page with that '/login' url the component is rendered.
Thanks for any help in advance!
EDIT: I'm not using PureComponent and wrapping exports in withRouter doesn't solve my problem too.
You should only have the top-level component (in your case, App) rendering the Router component. All of the components under that (ex. Main) should not have a Router in the render function. They will inherit the parent's Router. You can still use Link or Route components inside of the child components and they will navigate the parent Router.

cannot read property of map undefined using React redux

I'm trying to add information to a component but as soon as I click on the form button I get cannot read property map of undefined. Please help.
I've checked all the Db and routes, reducers etc. and they're all fine.
Here is component containing the form (The console.log returns "undefined")
import React from "react";
import { connect } from "react-redux";
import { addExercise } from "../actions/exercises";
class CreateExercise extends React.Component {
constructor(props) {
super(props);
this.state = {
newExercise: {},
};
}
handleSubmit(e) {
e.preventDefault();
e.target.reset();
this.props.dispatch(addExercise(this.state.newExercise));
}
updateDetails(e) {
let newExercise = this.state.newExercise;
newExercise[e.target.name] = e.target.value;
this.setState({ newExercise });
}
render() {
console.log("anything", this.props);
return (
<div className="form-container">
<form onSubmit={this.handleSubmit.bind(this)}>
<h2>Exercise Form</h2>
<div className="form">
<div>
<label>Name of Exercise:</label>
<input
name="exe_name"
type="text"
onChange={this.updateDetails.bind(this)}
/>
</div>
<div>
<label>Exercise Info:</label>
<input
name="exe_info"
type="text"
onChange={this.updateDetails.bind(this)}
/>
</div>
<div>
<label>Exercise Url:</label>
<input
name="exe_url"
type="text"
onChange={this.updateDetails.bind(this)}
/>
</div>
<div>
<label>Exercise Url2:</label>
<input
name="exe_url2"
type="text"
onChange={this.updateDetails.bind(this)}
/>
</div>
<div>
<label>Comment:</label>
<input
name="comment"
type="text"
onChange={this.updateDetails.bind(this)}
/>
</div>
</div>
<select name="plan_id" onChange={this.updateDetails.bind(this)}>
<option>Enter plan details</option>
{this.props.plans.map((plan, i) => {
return <option value={plan.plan_id}>{plan.sets}</option>;
})}
</select>
<input className="submit" type="submit" value="Submit" />
</form>;
</div>
);
}
}
const mapStateToProps = ({ plans }) => {
return { plans };
};
export default connect(mapStateToProps)(CreateExercise);
And here is the App component where it's being called.
import React from "react";
import { HashRouter as Router, Route } from "react-router-dom";
import { connect } from "react-redux";
import { getExercises } from "../actions/exercises";
import { getPlansRequest } from "../actions/plansActions";
import ExerciseList from "./ExerciseList";
import Header from "./Header";
import CreateExercise from "./CreateExercise";
import Single from "./Single";
import About from "./About";
import Home from "./Home";
import CreatePlan from "./CreatePlan";
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
showExerciseForm: false,
showPlanForm: false,
};
}
componentDidMount() {
this.props.dispatch(getPlansRequest());
this.props.dispatch(getExercises());
}
toggleForm(e) {
this.setState({ [e.target.name]: !this.state[e.target.name] });
}
render() {
return (
<Router>
<div className="app-container">
<div className="sidebar pure-u-1 pure-u-md-1-4">
<Header />
</div>
<Route
exact
path="/"
component={() => (
<button
name="showExerciseForm"
onClick={this.toggleForm.bind(this)}
>
{this.state.showExerciseForm ? "Cancel" : "Create Exercise"}
</button>
)}
/>
{this.state.showExerciseForm && (
<Route exact path="/" component={CreateExercise} />
)}
<Route
exact
path="/"
component={() => (
<button name="showPlanForm" onClick={this.toggleForm.bind(this)}>
{this.state.showPlanForm ? "Cancel" : "Create Plan"}
</button>
)}
/>
{this.state.showPlanForm && (
<Route exact path="/" component={CreatePlan} />
)}
<Route exact path="/exercises" component={ExerciseList} />
<Route
exact
path="/exercises/:id"
component={props => <Single {...props} />}
/>
<Route path="/about" component={About} />
<Route path="/" component={Home} />
</div>
</Router>
);
}
}
export default connect()(App);
You must send some props in the route to fetch them in component
In App component
{this.state.showExerciseForm && (<Route exact path="/" foobar="Something" component={CreateExercise} />)}
In CreateExercise fetch props by
this.props.foobar

Why does my React component remain in the DOM after navigating to another page?

I have a simple app with a home screen, a blog master list, and then blog detail page. Navigating from the home screen to the blog list and back works as expected. When I click on one of the blog posts the app navigates to the page and renders the blog post. But when I go back to the blog master list the blog post is now at the very bottom of the blog list. And if I then navigate back to the home page the same thing, the blog post is in the DOM behind the home page graphic.
I'm using react router 4.1.
Does it have to do with my route setup?
import React, { Component } from 'react'
import { BrowserRouter as Router, Route } from 'react-router-dom'
import NavBar from './components/NavBar'
import Blog from './pages/blog'
import Home from './pages/home'
import Post from './pages/post'
import './css/App.css'
class App extends Component {
render() {
return (
<Router>
<div className="App">
<NavBar />
<Route exact path='/' component={Home} />
<Route path='/blog' component={Blog} />
<Route path='/post/:slug' component={Post} />
</div>
</Router>
)
}
}
export default App
Or with my post component?
import React from 'react'
import fetch from 'isomorphic-unfetch'
import NavBar from '../components/NavBar'
import dateUtils from '../utilities/DateAndTime'
const classNames = require('classnames')
class Post extends React.Component {
constructor(props) {
super(props)
this.state = {
blogObject: null,
fetchBlogObject: false
}
this.fetchBlogObject = this.fetchBlogObject.bind(this)
this.createMarkup = this.createMarkup.bind(this)
this.assignStyleToCoverImage = this.assignStyleToCoverImage.bind(this)
this.formatDateString = this.formatDateString.bind(this)
}
componentWillMount() {
this.fetchBlogObject()
}
componentWillReceiveProps() {
this.fetchBlogObject()
}
fetchBlogObject() {
console.log('fetching')
this.setState({ fetchBlogObject: true })
fetch(`*******************`)
.then(response => response.json())
.then((responseJson) => {
console.log(responseJson)
this.setState({ blogObject: responseJson.object })
})
}
createMarkup(stringToConvertToHtml) {
return { __html: stringToConvertToHtml }
}
assignStyleToCoverImage() {
const style = {
background: `url(${this.state.blogObject.metadata.hero.url})`,
height: '35vh',
backgroundSize: 'cover',
backgroundPosition: 'center'
}
return style
}
formatDateString(dateString) {
console.log(dateString)
const d = `${dateUtils.returnMonthFromISODateString(dateString)} ${dateUtils.returnDateNumberFromISOString(dateString)}, ${dateUtils.returnFullYearFromISOString(dateString)} by Phil Andrews`
return d
}
render() {
const postContainerClasses = classNames({
'post-container': true
})
const postBodyClasses = classNames({
'post-body': true
})
return (
<div>
<NavBar />
{this.state.blogObject ?
<div className={postContainerClasses} >
<div className='header-image' style={this.assignStyleToCoverImage(this.state.blogObject)} />
<div className='post-body-padding'>
<div className='post-header-info'>
<h1 className='post-title'>{this.state.blogObject.title}</h1>
<h4 className='post-date'>{this.formatDateString(this.state.blogObject.created_at)}</h4>
</div>
<div className={postBodyClasses} dangerouslySetInnerHTML={this.createMarkup(this.state.blogObject.content)} />
</div>
</div>
: <div>Loading...</div>
}
</div>
)
}
}
export default Post
Or with my blog list button action for navigating to a post page?
<Link id={this.props.blogObject.slug} to={`/post/${this.props.blogObject.slug}`}>
<button className='blog-button' style={buttonStyle} id={this.props.blogObject.slug} />
</Link>
I'm not sure why it would continue to render the entire component but if I get rid of the <NavBar /> in the post component the issue goes away.
Not working:
return (
<div>
<NavBar />
{this.state.blogObject ?
<div className={postContainerClasses} >
<div className='header-image' style={this.assignStyleToCoverImage(this.state.blogObject)} />
<div className='post-body-padding'>
<div className='post-header-info'>
<h1 className='post-title'>{this.state.blogObject.title}</h1>
<h4 className='post-date'>{this.formatDateString(this.state.blogObject.created_at)}</h4>
</div>
<div className={postBodyClasses} dangerouslySetInnerHTML={this.createMarkup(this.state.blogObject.content)} />
</div>
</div>
: <div>Loading...</div>
}
</div>
)
Working:
return (
<div>
{this.state.blogObject ?
<div className={postContainerClasses} >
<div className='header-image' style={this.assignStyleToCoverImage(this.state.blogObject)} />
<div className='post-body-padding'>
<div className='post-header-info'>
<h1 className='post-title'>{this.state.blogObject.title}</h1>
<h4 className='post-date'>{this.formatDateString(this.state.blogObject.created_at)}</h4>
</div>
<div className={postBodyClasses} dangerouslySetInnerHTML={this.createMarkup(this.state.blogObject.content)} />
</div>
</div>
: <div>Loading...</div>
}
</div>
)

Categories