I am new to react, I am strugging in troubleshooting the error or mistake I am making. When I click on submit button after filling the data the page neither refreshes nor it shows any success message. Can anyone plz help me with this
This is my app.js
import React, { Component } from "react";
import { BrowserRouter as Router, Switch, Route, Link } from "react-router-dom";
import "bootstrap/dist/css/bootstrap.min.css";
import "./App.css";
import AuthService from "./services/auth.service";
import Login from "./components/login.component";
import Register from "./components/register.component";
import Home from "./components/home.component";
import Profile from "./components/profile.component";
import BoardUser from "./components/board-user.component";
import BoardAdmin from "./components/board-admin.component";
class App extends Component {
constructor(props) {
super(props);
this.logOut = this.logOut.bind(this);
this.state = {
showAdminBoard: false,
currentUser: undefined
};
}
componentDidMount() {
const user = AuthService.getCurrentUser();
if (user) {
this.setState({
currentUser: user,
showAdminBoard: user.roles.includes("ROLE_ADMIN")
});
}
}
logOut() {
AuthService.logout();
}
render() {
const { currentUser, showAdminBoard } = this.state;
return (
<Router>
<div>
<nav className="navbar navbar-expand navbar-dark bg-dark">
<Link to={"/"} className="navbar-brand">
Flight Reservation System
</Link>
<div className="navbar-nav mr-auto">
<li className="nav-item">
<Link to={"/home"} className="nav-link">
Home
</Link>
</li>
{showAdminBoard && (
<li className="nav-item">
<Link to={"/admin"} className="nav-link">
Admin
</Link>
</li>
)}
{currentUser && (
<li className="nav-item">
<Link to={"/user"} className="nav-link">
User
</Link>
</li>
)}
</div>
{currentUser ? (
<div className="navbar-nav ml-auto">
<li className="nav-item">
<Link to={"/profile"} className="nav-link">
{currentUser.username}
</Link>
</li>
<li className="nav-item">
<a href="/login" className="nav-link" onClick={this.logOut}>
LogOut
</a>
</li>
</div>
) : (
<div className="navbar-nav ml-auto">
<li className="nav-item">
<Link to={"/login"} className="nav-link">
Login
</Link>
</li>
<li className="nav-item">
<Link to={"/register"} className="nav-link">
Sign Up
</Link>
</li>
</div>
)}
</nav>
<div className="container mt-3">
<Switch>
<Route exact path={["/", "/home"]} component={Home} />
<Route exact path="/login" component={Login} />
<Route exact path="/register" component={Register} />
<Route exact path="/profile" component={Profile} />
<Route exact strict path="/user" component={BoardUser} />
<Route exact strict path="/admin" component={BoardAdmin} />
</Switch>
</div>
</div>
</Router>
);
}
}
export default App;
This is my board-admin.component.js:
import React, { Component } from "react";
import { BrowserRouter as Router, Switch, Route, Link } from "react-router-dom";
import "../Navbar.css";
import AddComponent from "./add-component";
import DeleteComponent from "./delete-component";
import UpdateComponent from "./update-component";
import UserService from "../services/user.service";
export default class BoardAdmin extends Component {
constructor(props) {
super(props);
this.state = {
content: ""
};
}
componentDidMount() {
UserService.getAdminBoard().then(
response => {
this.setState({
content: response.data
});
},
error => {
this.setState({
content:
(error.response &&
error.response.data &&
error.response.data.message) ||
error.message ||
error.toString()
});
}
);
}
render() {
return (
<Router>
<div>
<div className="navbars">
<ul>
<li>
<Link className="link" to={"/add"} >
Add
</Link>
</li>
<li>
<Link className="link" to={"/update"} >
Update
</Link>
</li>
<li>
<Link className="link" to={"/delete"}>
Delete
</Link>
</li>
</ul>
</div>
<div >
<Switch>
<Route exact path="/add" component={AddComponent} />
<Route exact path="/update" component={UpdateComponent} />
<Route path="/delete" component={DeleteComponent} />
</Switch>
</div>
</div>
</Router>
);
}
}
This is my add-component.js:
import React, { Component } from "react";
import FlightsService from "../services/flights.service";
export default class AddComponent extends Component {
constructor(props) {
super(props);
this.onChangeName = this.onChangeName.bind(this);
this.onChangeFrom = this.onChangeFrom.bind(this);
this.onChangeTo = this.onChangeTo.bind(this);
this.onChangeDate = this.onChangeDate.bind(this);
this.onChangeFare = this.onChangeFare.bind(this);
this.saveFlight = this.saveFlight.bind(this);
this.newFlight = this.newFlight.bind(this);
this.state = {
id: null,
name: "",
from: "",
to: "",
date: "",
fare: "",
submitted: false
};
}
onChangeName(e) {
this.setState({
name: e.target.value
});
}
onChangeFrom(e) {
this.setState({
from: e.target.value
});
}
onChangeTo(e) {
this.setState({
to: e.target.value
});
}
onChangeDate(e) {
this.setState({
date: e.target.value
});
}
onChangeFare(e) {
this.setState({
fare: e.target.value
});
}
saveFlight() {
var data = {
name: this.state.name,
from: this.state.from,
to:this.state.to,
date:this.state.date,
fare:this.state.fare
};
FlightsService.create(data)
.then(response => {
this.setState({
id: response.data.id,
name: response.data.name,
from: response.data.from,
to: response.data.to,
date:response.data.date,
fare:response.data.fare,
submitted: true
});
console.log(response.data);
})
.catch(e => {
console.log(e);
});
}
newFlight() {
this.setState({
id: null,
name: "",
from: "",
to: "",
date: "",
fare:"",
submitted: false
});
}
render() {
return (
<div className="submit-form">
{this.state.submitted ? (
<div>
<h4>You submitted successfully!</h4>
<button className="btn btn-success" onClick={this.newFlight}>
Add
</button>
</div>
) : (
<div>
<div className="form-group">
<label htmlFor="title">Name</label>
<input
type="text"
className="form-control"
id="title"
required
value={this.state.name}
onChange={this.onChangeName}
name="title"
/>
</div>
<div className="form-group">
<label htmlFor="description">From</label>
<input
type="text"
className="form-control"
id="description"
required
value={this.state.from}
onChange={this.onChangeFrom}
name="description"
/>
</div>
<div className="form-group">
<label htmlFor="description">To</label>
<input
type="text"
className="form-control"
id="description"
required
value={this.state.to}
onChange={this.onChangeTo}
name="description"
/>
</div>
<div className="form-group">
<label htmlFor="description">Date</label>
<input
type="text"
className="form-control"
id="description"
required
value={this.state.date}
onChange={this.onChangeDate}
name="description"
/>
</div>
<div className="form-group">
<label htmlFor="description">Fare</label>
<input
type="text"
className="form-control"
id="description"
required
value={this.state.fare}
onChange={this.onChangeFare}
name="description"
/>
</div>
<button onClick={this.saveFlight} className="btn btn-success">
Submit
</button>
</div>
)}
</div>
);
}
}
This is my axios related data:
import axios from "axios";
export default axios.create({
baseURL: "http://localhost:8002/api",
headers: {
"Content-type": "application/json"
}
});
This is my service:
import http from "../http-common";
class FlightsService {
create(data) {
return http.post("/flights", data);
}
update(id, data) {
return http.put(`/flights/${id}`, data);
}
delete(id) {
return http.delete(`/flights/${id}`);
}
}
export default new FlightsService();
have you tried annon functions ?
<button onClick={this.saveFlight} className="btn btn-success">
into
<button onClick={()=>{this.saveFlight()}} className="btn btn-success">
you are also binding the function of the click handler to the class of the component. I'm not sure if that is correct (not 100% on react best practices), I haven't dove too deeply into react - but using a master click Handler that handles all click events at the app level has been my strategy when binding functions... that has worked - but I can't guarantee it's not a terrible idea.
Related
Total Newbie in React and most of my learning is done through experimentation.
I have the following components:
App.js
import React, { Component } from 'react';
// Libraries and Utilities
import { BrowserRouter, Switch, Route } from 'react-router-dom';
// Components
import Layout from './components/layout/Layout';
import Home from './components/home/Home';
import Login from './components/login/Login';
class App extends Component {
static displayName = App.name;
render() {
return (
<BrowserRouter basename='/myapp>
<Layout>
<Switch>
<Route path="/" exact component={Home} />
<Route path='/login' component={Login} />
<Route path='/admin' component={Admin} />
</Switch>
</Layout>
</BrowserRouter>
);
}
}
export default App;
Layout.js
import React, { Component } from 'react';
import NavMenu from '../navigation/NavMenu';
class Layout extends Component {
render() {
return (
<div className="container-fluid">
<div className="row">
<NavMenu />
</div>
<div className="main layout">
{this.props.children}
</div>
<div className="row">
<Footer />
</div>
</div>
);
}
};
export default Layout;
NavMenu.js
import React, { Component } from 'react';
import { NavLink } from "react-router-dom";
import logo from '../../assets/logo.svg';
class navigation extends Component {
constructor(props) {
super(props)
this.state = {
loggedIn: false
}
}
render() {
return (
<div className="row">
<nav className="navbar navbar-expand navbar-dark bg-primary fixed-top">
<a className="navbar-brand" href="/">
<img src={logo} width="250" height="70" alt="" />
</a>
<div className="collapse navbar-collapse">
<ul className="navbar-nav mr-auto">
<li className="nav-item" to={'/'}>
<NavLink exact={true} className="navbar-brand" activeClassName='active' to='/'>Home</NavLink>
</li>
<li className="nav-item" to={'/admin1'}>
<NavLink exact={true} className="navbar-brand" activeClassName='active' to='/admin1'>Admin 1</NavLink>
</li>
<li className="nav-item" to={'/admin2'}>
<NavLink exact={true} className="navbar-brand" activeClassName='active' to='/admin1'>Admin 2</NavLink>
</li>
</ul>
<ul className="navbar-nav">
<li className="nav-item">
<NavLink exact={true} className="navbar-brand" activeClassName='active' to='/login'>
<i className="fa fa-sign-in" aria-hidden="true"></i>
</NavLink>
</li>
</ul>
</div>
</nav>
</div>
)
};
};
export default navigation;
Login .js
import React, { Component } from 'react';
class login extends Component {
constructor(props) {
super(props)
this.state = {
loginModel: {
UserName: '',
Password: ''
}
}
this.handleInputChange = this.handleInputChange.bind(this)
this.handleSubmit = this.handleSubmit.bind(this)
}
handleInputChange(event) {
const target = event.target
const value = target.type === 'checkbox' ? target.checked : target.value
const name = target.name
this.setState(prevState => ({
loginModel: {
...prevState.loginModel,
[name]: value
}
}))
}
handleSubmit(event) {
// At This Stage, I perform an API Call (via axios) and I get the Response Data.
const url = 'some url'
axios.post(url, this.state.loginModel).then((response) => {
if (response.status === 200) {
// Get token from response to be used in authenticated api calls.
const responseData = response.data
let authToken = responseData.token
console.log('authToken', authToken)
swal({
title: "My Application",
text: "Logon Successful.",
icon: "success"
}).then((value) => {
// Go to the Admin Home.
const path = '/admin'
this.props.history.push(path);
})
}
}, (err) => {
console.log(err.response)
const msg = err.response.data.message
const icon = err.response.data.icon
swal({
title: "My Application",
text: msg,
icon: icon
})
})
)
event.preventDefault();
}
componentDidMount() {
}
render() {
return (
<form className="form-signin" onSubmit={this.handleSubmit} >
<h3>Sign In</h3>
<div className="form-group">
<label>Username</label>
<input type="text" className="form-control" autoComplete="off"
id="input-username" name="UserName"
value={this.state.loginModel.UserName}
onChange={this.handleInputChange}
placeholder="Enter Username" />
</div>
<div className="form-group">
<label>Password</label>
<input type="password" className="form-control" autoComplete="off"
id="input-password" name="Password"
value={this.state.loginModel.Password}
onChange={this.handleInputChange}
placeholder="Enter Password" />
</div>
<button type="submit" className="btn btn-primary btn-block">Submit</button>
</form>
)
}
}
export default login;
Home.js
import React from 'react';
import { NavLink } from "react-router-dom";
const home = (props) => {
return (
<div className="container-fluid">
<div className="fill">
<div className="row">
<div className="col-md-4 col-sm-12">
<div className="card">
<div className="card-body flex-fill">
<h5 className="card-title">Info 1</h5>
<p className="card-text">
Details about Info 1
</p>
</div>
<div className="card-footer">
<NavLink exact={true} className="btn btn-primary btn-block" to='/info1'>Start</NavLink>
</div>
</div>
</div>
<div className="col-md-4 col-sm-12">
<div className="card">
<div className="card-body flex-fill">
<h5 className="card-title">Info 2</h5>
<p className="card-text">
Details about Info 2
</p>
</div>
<div className="card-footer">
<NavLink exact={true} className="btn btn-info btn-block" to='/info2'>Browse</NavLink>
</div>
</div>
</div>
<div className="col-md-4 col-sm-12">
<div className="card">
<div className="card-body flex-fill">
<h5 className="card-title">Info 3</h5>
<p className="card-text">
Details about Info 3
</p>
</div>
<div className="card-footer">
<NavLink exact={true} className="btn btn-success btn-block" to='/info3'>View</NavLink>
</div>
</div>
</div>
</div>
</div>
</div>
);
};
export default home;
My approach is quite simple. The application shows the Home component on initial load.
In the Navmenu, I have a link that navigates me to the Login screen.
In the Login screen, I have a login form where I am able to validate the user name and password via an API call.
I have multiple questions as I am still learning, but adding them here altogether as I feel it is all related.
Questions:
In my NavMenu component, I want to hide the admin1 and admin2 when on
initial load, and show it when the login is successful in the Login
component.
I want to prevent user from going to the route /admin1 and
/admin2 unless they are logged in. I am trying to read Protected
Routes but I am unable to get the hang of it as of yet.
In my Login screen, after successful login, one of the return value of the API
call is an API Key I can use for authorized calls. How can I make
that available such that I can access it from anywhere I perform an
API call.
I hope I provided enough context on what I am trying to achieve here. I know I need to brush up further my skills on how data communication between React happens.
Update: Been reading about Hooks, but I am unsure how to implement it here. Would I need to convert my JS files to use functional approach rather than class structure (ES6)?
Gracias.
I use redux for checking if use if logged in or not.
So when app start before show anything I check this.
and then I have privateRoute.
import React from "react";
import { Redirect, Route } from "react-router-dom";
import { useSelector } from "react-redux";
function PrivateRoute({ component: Component, ...props }) {
const isAuthenticated = useSelector(state => state.User.isLogin);
return (
<Route
render={props =>
isAuthenticated ? (
<Component {...props} />
) : (
<Redirect
to={{
pathname: "/login",
state: { from: props.location }
}}
/>
)
}
{...props}
/>
);
}
export default PrivateRoute;
and define IsAuthenticated component to redirect home page if user is already logged in:
import React from "react";
import { Redirect, Route } from "react-router-dom";
import { useSelector } from "react-redux";
function IsAuthenticated({ component: Component, ...props }) {
const isAuthenticated = useSelector(state => state.User.isLogin)
return (
<Route
{...props}
render={props =>
!isAuthenticated ? (
<Component {...props} />
) : (
<Redirect
to={{
pathname: "/",
state: { from: props.location }
}}
/>
)
}
/>
);
}
export default IsAuthenticated;
and define my routes here if user must authenticated to see them:
<Router>
<Switch>
{privateRoutes.map(({ path, component: Component }, idx) => (
<PrivateRoute
key={idx}
exact
path={path}
component={() => (
<SideNav>
<Component />
</SideNav>
)}
/>
))}
<IsAuthenticated exact path="/login" component={LoginPage} />
</Switch>
</Router>
here I use SideNav in my pages, you can use redux state in your Navbar component and with checking that you can show or hide whatever you want.
Or you can define two layout for your two types of your pages.
If you don't want to use redux, you can define state in App.js and pass it to your component or use react context.
I hope I helped you in your question.
Below is the code of the react component of my project. this.props.isAuthenticatedis working when I return the component but when I print this.props.isAuthenticated inside componentDidMount I am getting false(print logout). How do I get authentication status true or false in react component?
I have added redux already and login logout working fine.
import React, { Component } from "react";
import { NavLink, Route, withRouter } from "react-router-dom";
import NewsListView from "../Container/NewsListView";
import StatsView from "../Container/StatsView";
import VotingView from "../Container/VotingView.js";
import Rightsidebar from "../Container/rightsidebar";
import Footer from "./footer";
import Loginform from "../Container/loginform";
import SignUp from "../Container/SignUp";
import { connect } from "react-redux";
import * as actions from "../Store/actions/auth";
class Header extends React.Component {
componentDidMount() {
{
this.props.isAuthenticated ? console.log("login") : console.log("logout");
}
}
render() {
return (
<div>
<nav className="navbar navbar-inverse">
<div className="container-fluid">
<div className="navbar-header">
<button
type="button"
className="navbar-toggle"
data-toggle="collapse"
data-target="#myNavbar"
>
<span className="icon-bar" />
<span className="icon-bar" />
<span className="icon-bar" />
</button>
<NavLink className="navbar-brand" to="/">
Save4thPillar
</NavLink>
</div>
<div className="collapse navbar-collapse" id="myNavbar">
<ul className="nav navbar-nav">
<li>
<NavLink to="/" className="navlink">
Home
</NavLink>
</li>
<li>
<NavLink to="/news" className="navlink">
news
</NavLink>
</li>
<li>
<NavLink to="/stats" className="navlink">
stats
</NavLink>
</li>
{this.props.isAuthenticated ? (
<li>
<NavLink
to="/logout"
onClick={this.props.logout}
className="navlink"
>
Logout
</NavLink>
</li>
) : (
<li>
<NavLink to="/login" className="navlink">
Login
</NavLink>
</li>
)}
</ul>
</div>
</div>
</nav>
<div className="container">
<div className="row">
<div className="col-md-8">
<Route exact path="/" component={VotingView} {...this.props} />
<Route exact path="/news" component={NewsListView} />
<Route exact path="/stats" component={StatsView} />
<Route exact path="/login" component={Loginform} />
<Route exact path="/signup" component={SignUp} />
</div>
<div className="col-md-4">
<Rightsidebar />
</div>
<div />
</div>
<Footer />
</div>
</div>
);
}
}
const mapDispatchToProps = dispatch => {
return {
logout: () => dispatch(actions.logout())
};
};
export default withRouter(
connect(
null,
mapDispatchToProps
)(Header)
);
You should implement the Header component's constructor. to use props in lifecycles
class Header extends React.Component {
componentDidMount() {
{
this.props.isAuthenticated ? console.log("login") : console.log("logout");
}
constructor(props){
super(props);
}
[...]
}
I'm trying to redirect the user back to the index page, when a user clicks handleSubmit. However the data gets sent to the backend, but stays on the page with the user information still keyed in.
It does not render an error.
Here is the demo.
https://stackblitz.com/edit/react-h9ekc4
Navbar
import React, { Component } from 'react';
import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom";
import SignUp from './SignUp';
import SignIn from './SignIn';
const Navbar = () => {
return(
<Router>
<div>
<nav className="navbar navbar-expand-lg navbar-light bg-light ">
<button className="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarsExample08" aria-controls="navbarsExample08" aria-expanded="false" aria-label="Toggle navigation">
<span className="navbar-toggler-icon"></span>
</button>
<div className="collapse navbar-collapse justify-content-md-center" id="navbarsExample08">
<ul className="navbar-nav">
<li className="nav-item">
<Link className="nav-link" to="/SignUp">Sign Up </Link>
</li>
<li className="nav-item">
<Link className="nav-link" to="/SignIn">Sign In </Link>
</li>
</ul>
</div>
</nav>
<Route path="/SignUp" component={SignUp} />
<Route path="/SignIn" component={SignIn} />
</div>
</Router>
);
}
export default Navbar;
SignUp.js
import React, {Component} from 'react';
import { withRouter } from "react-router-dom";
import { connect } from "react-redux";
import {signUp ,onEmailSignUpChangeAction,onPasswordSignUpChangeAction} from '../actions/';
class SignUp extends Component {
state = {
email: "",
password: ""
}
// onChange = (e) =>{
// this.setState({
// [e.target.name] : e.target.value
// })
// }
handleSubmit = (e) =>{
e.preventDefault();
const register = this.props.signUp();
// this.props.history not working
(register === true) && this.props.history.push('/');
console.log(this.state);
}
render() {
return (
<div className="container">
<div className="row">
<div className="col-md-6">
<h1>Sign Up</h1>
<div>
<div className="form-group">
<label htmlFor="exampleInputEmail1">Email address</label>
<input
type="email"
className="form-control"
id="email"
onChange={this.props.onEmailSignUpChangeAction}
aria-describedby="emailHelp"
value={this.props.emailSignUp}
placeholder="Enter email"/>
<small id="emailHelp" className="form-text text-muted">We'll never share your email with anyone else.</small>
</div>
<div className="form-group">
<label htmlFor="exampleInputPassword1">Password</label>
<input
type="password"
className="form-control"
id="password"
value={this.props.passwordSignUp}
onChange={this.props.onPasswordSignUpChangeAction}
placeholder="Password"/>
</div>
<button type="submit" onClick={this.handleSubmit} className="btn btn-primary">Submit</button>
</div>
</div>
</div>
</div>
);
}
}
const mapStateToProps = (state) => ({
user: state.auth.user,
emailSignUp:state.signUpAuth.emailSignUp,
passwordSignUp:state.signUpAuth.passwordSignUp
})
const mapDispatchToProps = (dispatch) => ({
signUp: () => dispatch(signUp()),
onEmailSignUpChangeAction: (event) => dispatch(onEmailSignUpChangeAction(event.target.value)),
onPasswordSignUpChangeAction: (event) => dispatch(onPasswordSignUpChangeAction(event.target.value)),
});
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(SignUp));
since your action signUp() is not returning anything.
register = this.props.signUp() is always undefined and hence the below line never executes..
(register === true) && this.props.history.push('/');
try returning true/false based on your logic and then try running your code again
Your dispatch call this.props.signUp() is returning undefined, hence this.props.history.push('/') is not executing.
just tried to add a console.log
handleSubmit = (e) =>{
e.preventDefault();
const register = this.props.signUp();
console.log(register);
(register === true) && this.props.history.push('/');
console.log(this.state);
}
register dispatch should be returning boolean.
I use client-side routes(HashRouter, Link). In App component i have 3 components - Home, Page1, Page2. And i want to get data from server and on Page1 display this data dynamicaly. But when i go to this page i have error:
When i don't configure Page1 as class and configure it such as const (just as in app.jsx Home component) all work fine, but when i try to configure it like a class, i get this error which i described below.
Here my code:
app.jsx
import React from 'react'
import {
HashRouter as Router,
Route,
Link
} from 'react-router-dom'
import {
Container,
Row,
Col
} from 'react-grid-system';
import Page1 from "./page1.jsx";
const Home = () => (
<div class="container-fixed">
<div class="row">
<div class="col-l-4">
<h2 class="underline">Home</h2>
</div>
</div>
</div>
)
const Subpage = ({ match }) => (
<div>
<h3>{match.params.topicId}</h3>
</div>
)
const Page2 = ({ match }) => (
<div class="container-fixed">
<div class="row">
<div class="col-l-4">
<h2 class="underline">Subpages</h2>
<ul class="content-list">
<li class="content-list-item">
<Link to={`${match.url}/subpage1`}>
subpage1
</Link>
</li>
<li class="content-list-item">
<Link to={`${match.url}/subpage2`}>
subpage2
</Link>
</li>
<li class="content-list-item">
<Link to={`${match.url}/subpage3`}>
subpage3
</Link>
</li>
</ul>
<Route path={`${match.path}/:topicId`} component={Subpage}/>
<Route exact path={match.path} render={() => (
<h3>Please select a subpage.</h3>
)}/>
</div>
</div>
</div>
)
const App = () => (
<Router>
<Container>
<Row>
<Col md={2}>
<h2 class="underline">Menu</h2>
<ul class="content-list">
<li class="content-list-item">
<Link to="/">Home</Link>
</li>
<li class="content-list-item">
<Link to="/page1">Page1</Link>
</li>
<li class="content-list-item">
<Link to="/page2">Page2</Link>
</li>
</ul>
</Col>
<Col>
<Route exact path="/" component={Home}/>
<Route path="/page1" component={Page1}/>
<Route path="/page2" component={Page2}/>
</Col>
</Row>
</Container>
</Router>
)
export default App
page1.jsx
import React, {Component} from 'react';
const Row_ = function(props){
const {id, content} = props;
return (
<div>
id: {id}
content: {content}
</div>
);
}
class Page1 extends React.Component {
constructor(props){
super(props);
this.state = {
datas: [
{id: 14, content: "test"},
{id: 25, content: "test2"},
{id: 75, content: "test3"},
]
};
}
handleClick() {
let fetchedData = gerData();
this.addDataToHTML(fetchedData.id, fetchedData.content);
}
getData() {
fetch('/testdata', {
method: 'GET',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
}
})
.then(results => {
return results.json();
})
}
addDataToHTML(id, content){
const datas = [...this.state.datas,
{value: id, checked: content}
];
this.setState({
datas,
});
}
render(){
<div class="container-fixed">
<div class="row">
<div class="col-l-4">
<h2 class="underline">Page11</h2>
{this.state.datas.map((row, idx) => {
return(
<Row_
id={row.id}
content={row.content}
/>
)
})
}
<button onClick={this.handleClick}>
Get data
</button>
</div>
</div>
</div>
}
}
export default Page1
index.jsx
import React, {Component} from 'react';
import ReactDOM from 'react-dom';
import App from "./app.jsx";
import "../t_styles/css/components.min.css";
import "../t_styles/js/components.min.js";
import $ from "jquery";
ReactDOM.render((
<App></App>
), document.getElementById('index'))
1. use className instead of class.
2. add return statement in your render method of Page1 component
render(){
return (<div className="container-fixed">
<div className="row">
<div className="col-l-4">
<h2 className="underline">Page11</h2>
{this.state.datas.map((row, idx) => {
return(
<Row_
id={row.id}
content={row.content}
/>
)
})
}
<button onClick={this.handleClick}>
Get data
</button>
</div>
</div>
</div>)
}
Though I can't see the actual errors, my guess is that your handlers are not bound to the class instance, and therefore you can't access it via this.
So Either bind them to the class (this usually done inside the constructor):
this.handleClick = this.handleClick.bind(this);
this.getData= this.getData.bind(this);
this.addDataToHTML= this.addDataToHTML.bind(this);
Or use an arrow function syntax that will use this in a lexical context:
handleClick = () => {
let fetchedData = gerData();
this.addDataToHTML(fetchedData.id, fetchedData.content);
}
Im'm trying to implement a search bar in my nav bar that will bring me a list of cities and according to the selected city it has to update the list of offers in the main page,since the offers is filtered by cities, the thing is, the navbar is one component and the offers is in another component, if I search for a city in my navbar and hit enter, how can the offer component listen to it and make the call to the api based by the searched city? here is my code:
Navbar:
class NavigationBar extends React.Component {
constructor(props) {
super(props);
this.cityoffer = this.cityoffer.bind(this);
}
cityoffer(e) {
e.preventDefault();
this.props.history.push("/home");
console.log("cities");
}
render(){
const { isAuthenticated } = this.props.auth;
const userLinks = (
<form className="form-inline my-2 my-lg-0 ml-auto" onSubmit={this.cityoffer}>
<input className="form-control mr-sm-2" type="search" placeholder="Cidade" aria-label="Search"/>
<button className="btn btn-outline-success my-2 my-sm-0" type="submit">Procurar</button>
</form>
);
const guestLinks = (
<ul className="navbar-nav ml-auto">
<li className="nav-item">
<Link to="/login" className="nav-link">Entrar</Link>
</li>
<li className="nav-item">
<Link to="/signup" className="nav-link">Registrar</Link>
</li>
</ul>
);
return (
<nav className="navbar navbar-expand-lg navbar-dark bg-dark">
<button className="navbar-brand brandbutton" onClick={this.brand}><img src={imglogo} className="imagemNav" alt="logo"/></button>
<button className="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNavAltMarkup" aria-controls="navbarNavAltMarkup" aria-expanded="false" aria-label="Toggle navigation">
<span className="navbar-toggler-icon"></span>
</button>
<div className="navbar-collapse collapse w-100 order-3 dual-collapse2" id="navbarNavAltMarkup">
{ isAuthenticated ? userLinks : guestLinks }
</div>
</nav>
);
}
}
NavigationBar.propTypes = {
auth: PropTypes.object.isRequired,
logout: PropTypes.func.isRequired
}
function mapStateToProps(state) {
return {
auth: state.auth
};
}
export default withRouter(connect(mapStateToProps, { logout })(NavigationBar));
Offers:
class Anuncios extends React.Component {
constructor(props){
super(props);
this.state = {
city: 2958,
}
}
componentWillReceiveProps = (nextProps) => {
console.log(nextProps)
}
componentDidMount() {
this.props.fetchAnuncios(this.state.city);
}
render() {
return (
<div className="pagemargin">
<AnunciosList anuncios={this.props.anuncios}/>
</div>
);
}
}
Anuncios.propTypes = {
anuncios: PropTypes.array.isRequired,
fetchAnuncios: PropTypes.func.isRequired,
}
function mapStateToProps(state) {
return {
anuncios: state.anuncios
}
}
export default connect(mapStateToProps, {fetchAnuncios, searchCidadesRequestID})(Anuncios);
App:
class App extends Component {
render() {
return (
<div className="App">
<NavigationBar />
<FlashMessagesList/>
</div>
);
}
}
export default App;
routes:
const AppRouter = () => (
<Router>
<div>
<AlertProvider template={AlertTemplate} {...options}>
<App/>
<Switch>
<Route exact path="/" component={Intro}/>
<Route path="/home" component={Home}/>
<Route path="/signup" component={SignUp}/>
<Route path="/login" component={LoginPage}/>
<Route path="/filtrar" component={Filtrar}/>
<Route path="/cupons" component={requireAuth(Cupons)}/>
<Route path="/perfil" component={requireAuth(Perfil)}/>
<Route path="/anuncio/:id" component={AnuncioDetalhes}/>
<Route component={NoMatch}/>
</Switch>
</AlertProvider>
</div>
</Router>
);
like that: