this.props.onAdd is not a function? - javascript

I try to nest a component with a form to add records to the database, within a component that lists everything, but pressing submit gives me this error: "Uncaught TypeError: this.props.onAdd is not a function."
I have reviewed everything from top to bottom, but I don't see the problem, since it is A method that I used before without problems, but i'm new at this, so...
I'm using Laravel in the backend (in case you need to know).
Can somebody help me please?
thanks for your time!!
This is my father component:
import React, { Component } from 'react';
import Empresa from './Empresa';
import CrearEmpresa from './CrearEmpresa';
export default class Empresas extends Component {
constructor() {
super();
this.state = {
empresas: [],
empresaActual: null
}
this.handleAddEmpresa = this.handleAddEmpresa.bind(this);
}
componentDidMount() {
fetch('/api/empresas')
.then(response => {
return response.json();
})
.then(empresas => {
this.setState({ empresas });
});
}
renderEmpresas() {
return this.state.empresas.map(empresa => {
return (
<div className="card" key={empresa.id}>
<div className="card-body">
<h5 className="card-title">{empresa.nombre}</h5>
<p className="card-text">{empresa.cif} </p>
<p className="card-text">{empresa.direccion} </p>
<p className="card-text"> {empresa.telefono} </p>
<p className="card-text"> {empresa.mail}</p>
<p className="card-text"> {empresa.entradas}</p>
</div>
<div className="card-footer">
<a onClick={()=>this.handleClick(empresa)} >Más</a>
</div>
</div>
);
})
}
handleClick(empresa) {
this.setState({empresaActual:empresa});
}
handleAddEmpresa (empresa) {
empresa.entradas = Number(empresa.entradas);
fetch( 'api/empresas/', {
method:'post',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(empresa)
})
.then(response => {
return response.json();
})
.then(data => {
this.setState((prevState)=> ({
empresas: prevState.empresas.concat(data),
empresaActual : data
}))
})
}
render() {
return (
<div className="container" id="empresas" >
<div className="row">
<div className="col s12 offset-m l8">
<h3> Empresas </h3>
{ this.renderEmpresas() }
</div>
<Empresa empresa={this.state.empresaActual} />
</div>
<div>
<CrearEmpresa onAdd={this.handleAddEmpresa} />
</div>
</div>
);
}
}
```````````````````````````````````````````````````````````````````````````````````````````````````
And this is the child:
```````````````````````````````````````````````````````````````````````````````````````````````````
import React, {Component} from 'react';
export default class CrearEmpresa extends Component {
constructor(props) {
super(props);
this.state = {
nuevaEmpresa: {
nombre: '',
direccion: '',
telefono: '',
mail: '',
entradas: 0
}
}
this.handleSubmit = this.handleSubmit.bind(this);
this.handleChange = this.handleChange.bind(this);
}
handleChange (e){
this.setState ({
[e.target.id]: e.target.value
})
}
handleSubmit(e) {
e.preventDefault();
console.log(this.state);
this.props.onAdd(this.state.nuevaEmpresa);
}
render() {
return(
<div>
<div className="container">
<form onSubmit={this.handleSubmit} className="transparent">
<h5 className="grey-text text-darken-3">Nueva Empresa</h5>
<div className="input-field">
<label htmlFor="nombre">Nombre</label>
<input type="text" name="nombre" id="nombre" onChange={this.handleChange} />
</div>
<div className="input-field">
<label htmlFor="direccion">Dirección</label>
<textarea className="materialize-textarea" name="direccion" id="direccion"
onChange={this.handleChange}></textarea>
</div>
<div className="input-field">
<label htmlFor="telefono">Teléfono</label>
<br />
<input type="tel" name="telefono" id="telefono" onChange={this.handleChange} />
</div>
<div className="input-field">
<label htmlFor="mail">Mail</label>
<br />
<input type="email" name="mail" id="mail" onChange={this.handleChange} />
</div>
<div className="input-field">
<label htmlFor="entradas">Número de entradas</label>
<input type="number" name="entradas" id="entradas" min="10" max="50000" step="5"
onChange={this.handleChange} />
</div>
<input type="submit" value="submit" />
</form>
</div>
</div>
)
}
}
``````````````````````````````````````````````````````````````````````````````````````````````

Related

How to transfer data between two child component in react js?

Actually I'm creating a front-end in which I am taking a mobile number as input on 1st page then after checking mobile number I am moving to OTP page. In OTP page I am taking otp as input and have to send both otp and mobile number to the backend. I am able to pass the otp but dont know how to pass the mobile number as I have taken it as input in the previous page.
Here is Signup Component which will take mobile number input
import React from 'react';
import './Signup.css';
class Signup extends React.Component {
constructor(props){
super(props);
this.state={
mobile:''
}
}
onMobileChange = (event) => {
this.setState({mobile: event.target.value})
}
onSubmitSignup = () => {
fetch('https://cors-anywhere.herokuapp.com/http://8080/signup/checkMobile',{
method:'post',
headers:{'Content-Type':'application/json'},
body: JSON.stringify({
mobile:this.state.mobile
})
})
.then(response => response.json())
.then(data =>{
if(data.content === 'OK'){
this.props.loadNewUser(this.state.mobile);
this.props.onRouteChange('otp','nonav');
}
})
// this.props.onRouteChange('otp','nonav');
}
render(){
const { onRouteChange} = this.props;
return(
<div className='container'>
<div className='mt6'>
<img src={require('./logo.png')} className='logoimg' alt='logo'/>
</div>
<h3 className='text-center b' style={{font:"Montserrat"}}>FOODVIRAAM</h3>
<div>
<article className="br3 ba dark-gray b--white mv4 w-100 w-50-m w-25-l mw6 shadow-6 center">
<main className="pa4 black-80">
<div className="measure">
<fieldset id="sign_up" className="ba b--transparent ph0 mh0">
<div className="mt1">
<label className="db fw5 lh-copy f3" htmlFor="email-address" style={{font:"Montserrat"}}>Enter your mobile number</label>
<input
className="pa2 input-reset ba bg-transparent hover-bg-black bw1 br2 w-100"
type="number"
name="mobile"
id="mobile"
style={{borderColor:"#ffde59",lineHeight:"28px"}}
onChange={this.onMobileChange}
/>
</div>
</fieldset>
<div className="tr">
<input
onClick={this.onSubmitSignup}
className="pv2 input-reset ba b--white bg-transparent grow pointer f3 dib" style={{font:"Montserrat"}} type="submit" value="Send OTP"/>
</div>
</div>
</main>
</article>
</div>
<h5 className="tc mt5" style={{font:"Montserrat"}}>{"#HighwayKaHygienicPitStop"}</h5>
</div>
);
}
}
export default Signup;
OTP component In which I will take OTP as input and then have to send otp and mobile number on Submit
import React from 'react';
import './Signup.css';
class Otp extends React.Component{
constructor(props){
super(props);
this.state={
otp:''
}
}
onOtpChange = (event) => {
this.setState({otp: event.target.value})
}
onSubmitOtp = () => {
console.log(this.props.mobile);
fetch('https://cors-anywhere.herokuapp.com/http://8080/signup/validateOtp',{
method:'post',
headers:{'Content-Type':'application/json'},
body: JSON.stringify({
mobile:this.props.mobile,
otp:this.state.otp
})
})
.then(response => response.json())
.then(data =>{
if(data.content === 'OK'){
// this.props.loadNewUser(this.state.otp);
this.props.onRouteChange('createprofile','nonav');
}
})
this.props.onRouteChange('otp','nonav');
}
render(){
const { mobile,onRouteChange} = this.props;
return(
<div className='container'>
<div className='mt6'>
<img src={require('./logo.png')} className='logoimg' alt='logo'/>
</div>
<h3 className='text-center b' style={{font:"Montserrat"}}>FOODVIRAAM</h3>
<div>
<article className="br3 ba dark-gray b--white mv4 w-100 w-50-m w-25-l mw6 shadow-6 center">
<main className="pa4 black-80">
<div className="measure">
<fieldset id="sign_up" className="ba b--transparent ph0 mh0">
<div className="mt1">
<label className="db fw5 lh-copy f3" htmlFor="email-address" style={{font:"Montserrat"}}>Verify OTP</label>
<input
className="pa2 input-reset ba bg-transparent hover-bg-black bw1 br2 w-100"
type="number"
name="mobile-number"
id="mobile-number"
style={{font:"Montserrat", borderColor:"#ffde59",lineHeight:"28px"}}
onChange={this.onOtpChange}
/>
</div>
</fieldset>
<div className="tr">
<input
onClick={this.onSubmitOtp}
className="pv2 input-reset ba b--white bg-transparent grow pointer f3 dib" style={{font:"Montserrat"}} type="submit" value=""/>
</div>
</div>
</main>
</article>
</div>
<h5 className="tc mt5" style={{font:"Montserrat"}}>{"#HighwayKaHygienicPitStop"}</h5>
</div>
);
}
}
export default Otp;
And this is the parent class
class App extends Component {
constructor(props){
super(props);
this.state={
route:'signup',
route1:'nonav',
newuser:{
mobile:''
}
}
}
loadNewUser = (mobile)=>{
this.setState({user: {
mobile:mobile
}})
console.log(mobile);
}
onRouteChange = (route, route1) =>{
this.setState({route:route});
this.setState({route1:route1});
}
render(){
return (
<div className="App">
{this.state.route1==='nav'
? <div>
<Navigation onRouteChange={this.onRouteChange}/>
{ this.state.route==='editmnc'
? <EditMNC parentMethod={this.onRouteChange}>{this.props.children}</EditMNC>
:<Revenue onRouteChange={this.onRouteChange}/>
}
</div>
}
: <div>
{ this.state.route==='signup'
? <Signup loadNewUser={this.loadNewUser} onRouteChange={this.onRouteChange}/>
: <div>
{ this.state.route==='otp'
? <Otp mobile={this.state.newuser.mobile} onRouteChange={this.onRouteChange}/>
: <div>
{ this.state.route==='createprofile'
? <CreateProfile onRouteChange={this.onRouteChange} />
: <div>
{ this.state.route==='signin'
? <Signin onRouteChange={this.onRouteChange} />
: <AddItem onRouteChange={this.onRouteChange}/>
}
</div>
}
</div>
}
</div>
}
</div>
}
</div>
);
}
}
Use localStorage or Cookies to store your phone number on one page and on the next page, you can easily retrieve the data by whatever medium you choose. Since storing on either of them persist your data, you don't need to worry about an accidental refresh of the page.
Don't use Redux or Context API, as they don't persist the data.
Example :-
Using the localStorage API
// storing the phone number on your first page.
localStorage.setItem('$$NAMESPACE__phone_number', phoneNumber)
// getting the phone number on your second.
const phoneNumber = localStorage.getItem('$$NAMESPACE__phone_number')
Use Redux it's a bit complicated but It is used when you need to transfer data from child to parent,
You can also get the data that you sent by props to child and got a return value
https://redux.js.org

Constructor is called twice in React component

I am trying to use this component that I found in a medium article. I am creating a chatroom. The component below is the chatbox that I am trying to modify and reuse. For some reason the constructor is being called twice. I am new to react. I guessed it does this because of the state change.
import React from "react";
import io from "socket.io-client";
class Chat extends React.Component{
constructor(props){
super(props);
console.log("constructor called");
this.state = {
username: '',
message: '',
messages: []
};
this.socket = io('localhost:5000');
console.log("socket created");
this.socket.on('RECEIVE_MESSAGE', function(data){
addMessage(data);
});
const addMessage = data => {
console.log(data);
this.setState({messages: [...this.state.messages, data]});
console.log(this.state.messages);
};
this.sendMessage = ev => {
ev.preventDefault();
this.socket.emit('SEND_MESSAGE', {
author: this.state.username,
message: this.state.message
})
this.setState({message: ''});
}
}
render(){
return (
<div className="container">
<div className="row">
<div className="col-4">
<div className="card">
<div className="card-body">
<div className="card-title">Global Chat</div>
<hr/>
<div className="messages">
{this.state.messages.map(message => {
return (
<div>{message.author}: {message.message}</div>
)
})}
</div>
</div>
<div className="card-footer">
<input type="text" placeholder="Username" value={this.state.username} onChange={ev => this.setState({username: ev.target.value})} className="form-control"/>
<br/>
<input type="text" placeholder="Message" className="form-control" value={this.state.message} onChange={ev => this.setState({message: ev.target.value})}/>
<br/>
<button onClick={this.sendMessage} className="btn btn-primary form-control">Send</button>
</div>
</div>
</div>
</div>
</div>
);
}
}
export default Chat;

innerHTML works only once in my react app

What I am trying to do is clear my container div when the user hits the search button so all the existing search results are removed.
The problem is I am using innerHTML to clear the container div but it only works for the first time.
If you search for something for the second time then you will see no results are rendered.
I've just started learning reactjs.
Here is my code (I have removed the API key and the id just FYI).
import React from "react";
import Recipe from "./Recipe";
import "./styles.css";
export default class App extends React.Component {
constructor() {
super();
this.state = {
searchQuery: "Icecream",
searchData: [],
error: false,
loader: false
};
this.handleSubmit = this.handleSubmit.bind(this);
this.handleChange = this.handleChange.bind(this);
}
handleChange(e) {
this.setState({
[e.target.name]: e.target.value
});
}
handleSubmit(e) {
e.preventDefault();
document.querySelector(".control.field").classList.add("is-loading");
this.setState({
error: false,
loader: true
});
document.querySelector(".columns").innerHTML = "test";
fetch(
`https://api.edamam.com/search?q=${
this.state.searchQuery
}&app_id=id&app_key=key`
)
.then(response => response.json())
.then(data => {
this.setState({
searchData: data.hits
});
})
.catch(err => {
this.setState({
error: true
});
})
.finally(() => {
document.querySelector(".control.field").classList.remove("is-loading");
this.setState({
loader: false
});
});
}
renderIngredients = arr => arr.map((el, index) => <li key={index}>{el}</li>);
render() {
let result;
result = this.state.searchData.map((el, index) => (
<Recipe
key={index}
image={el.recipe.image}
title={el.recipe.label}
ingredients={this.renderIngredients(el.recipe.ingredientLines)}
/>
));
return (
<div>
<form className="px-3 py-3" onSubmit={this.handleSubmit}>
<div className="field is-grouped">
<p className="control field is-expanded">
<input
className="input is-rounded"
type="text"
placeholder="Find a recipe"
name="searchQuery"
value={this.state.searchQuery}
onChange={this.handleChange}
/>
</p>
<p className="control">
<button className="button is-primary">Search</button>
</p>
</div>
</form>
{this.state.loader ? (
<div className="spinner-box">
<div className="three-quarter-spinner" />
</div>
) : (
""
)}
{this.state.error ? (
<div className="px-3 py-3">
<div className="notification is-danger">
Some error occured. Unable to fetch
</div>
</div>
) : (
<div className="columns is-multiline px-3 py-3 is-mobile">
{result}
</div>
)}
</div>
);
}
}
Recipe component :
import React from "react";
export default class Recipe extends React.Component {
render() {
return (
<div className="column is-one-quarter-desktop is-half-mobile">
<div className="card">
<div className="card-image">
<figure className="image is-4by3">
<img src={this.props.image} alt="" />
</figure>
</div>
<div className="card-content">
<p className="title is-6">{this.props.title}</p>
<ul>{this.props.ingredients}</ul>
</div>
</div>
</div>
);
}
}
What do you think about using new state for that?
What I mean is that:
this.state = {
...,
focusSearch: false
}
const handleFocus = () => {
this.setState({ ...this.state, focusSearch: true});
}
<input
className="input is-rounded"
type="text"
placeholder="Find a recipe"
name="searchQuery"
value={this.state.searchQuery}
onFocus={this.handleFocus}
onChange={this.handleChange}
/>
render() {
return (
{
focusSearch ? <div></div> : <></>;
}
)
}
I figured it out this morning. It can be done easily using conditional rending and ternary operator.
Thank you, everyone.

How to call Promise.all in a handler function in React.js

I have two API calls that I am trying to make based on the input;
api.js
import axios from 'axios';
export const getWeather = input => {
};
export const getForecast = input => {
};
And in my React component:
import React, { Component } from 'react';
import WeatherDisplay from './WeatherDisplay';
import * as api from '../utils/api';
import dataTracker from '../utils/dataTracker';
import '../scss/app.scss';
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
input: '',
weatherFromInput: null,
};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
componentDidMount() {
console.dir(dataTracker);
}
handleChange(event) {
this.setState({
input: event.target.value,
});
}
// prettier-ignore
handleSubmit(event) {
event.preventDefault();
var promises = Promise.all(api.getWeather(this.state.input), api.getForecast(this.state.input))
promises.then(function(input) {
this.setState({ weatherFromInput: input[0], input: '' });
console.log("input", input[0]);
}.bind(this));
}
render() {
return (
<div className="container">
<div className="container">
<form name="weatherApp" onSubmit={this.handleSubmit}>
<h2>Open Weather App</h2>
<div className="row">
<div className="one-half column">
<label htmlFor="insertMode">Insert your location</label>
<input
name="zipcode"
className="u-full-width"
placeholder="please enter city or zipcode"
type="text"
autoComplete="off"
value={this.state.input}
onChange={this.handleChange}
/>
</div>
<div className="one-half column">
<label htmlFor="showMin">show minimum</label>
<input type="checkbox" />
<label htmlFor="showMax">show maximum</label>
<input type="checkbox" />
<label htmlFor="showMean">show mean</label>
<input type="checkbox" />
</div>
</div>
<div className="row">
<div className="two-half column">
<input type="submit" value="Submit" />
</div>
</div>
</form>
</div>
<div className="container">
<div className="row">
<div className="twelve columns">
{this.state.weatherFromInput !== null ? <WeatherDisplay weather={this.state.weatherFromInput} /> : null}
</div>
</div>
</div>
</div>
);
}
}
I get this error:
App.js:77 Uncaught (in promise) TypeError: undefined is not a function
Any help will be appreciated!
I believe Promise.all() needs an array, so:
var promises = Promise.all(api.getWeather(this.state.input), api.getForecast(this.state.input))
should be
var promises = Promise.all([api.getWeather(this.state.input), api.getForecast(this.state.input)])

where to put my header and footer tags in reactjs

import React, { Component } from 'react';
import { connect } from 'react-redux';
import { login } from '../../redux/reducer';
import './LoginForm.css';
class LoginForm extends Component {
constructor(props) {
super(props);
this.state = {};
this.onSubmit = this.onSubmit.bind(this);
}
render() {
let {username, password} = this.state;
let {isLoginPending, isLoginSuccess, loginError} = this.props;
return (
<header>
<h1>Company Login</h1>
</header>
<form name="loginForm" onSubmit={this.onSubmit}>
<div className="form-group-collection">
<div className="form-group">
<label>Username/User ID:</label>
<input name="username" onChange={e => this.setState({username: e.target.value})} value={username}/>
</div>
<div className="form-group">
<label>Password:</label>
<input type="password" name="password" onChange={e => this.setState({password: e.target.value})} value={password}/>
</div>
</div>
<br/>
<input type="submit" value="Login" />
</form>
<footer>Copyright © multihands.com. </footer>
)
}
onSubmit(e) {
e.preventDefault();
let { username, password } = this.state;
this.props.login(username, password);
this.setState({
username: '',
password: ''
});
}
}
const mapStateToProps = (state) => {
return {
isLoginPending: state.isLoginPending,
isLoginSuccess: state.isLoginSuccess,
loginError: state.loginError
};
}
const mapDispatchToProps = (dispatch) => {
return {
login: (username, password) => dispatch(login(username, password))
};
}
export default connect(mapStateToProps, mapDispatchToProps)(LoginForm);
This is my login page i want to add header in my page.. I added it already as shown in the code...But unfortunetly error occurs after running.. Where does I put my header and footer tag in my code.. If we put it in form the code runs..But the css applied to the form is affected by adding the footer and header.. So I need the correct way to place header and footer without intrude my form..
Issue is that return statement must contain a single element only and your code contains three. So basically this should work:
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { login } from '../../redux/reducer';
import './LoginForm.css';
class LoginForm extends Component {
constructor(props) {
super(props);
this.state = {};
this.onSubmit = this.onSubmit.bind(this);
}
render() {
let { username, password } = this.state;
let { isLoginPending, isLoginSuccess, loginError } = this.props;
return (
<div>
<header>
<h1>Company Login</h1>
</header>
<form name="loginForm" onSubmit={this.onSubmit}>
<div className="form-group-collection">
<div className="form-group">
<label>Username/User ID:</label>
<input name="username" onChange={e => this.setState({ username: e.target.value })} value={username} />
</div>
<div className="form-group">
<label>Password:</label>
<input type="password" name="password" onChange={e => this.setState({ password: e.target.value })} value={password} />
</div>
</div>
<br />
<input type="submit" value="Login" />
</form>
<footer>Copyright © multihands.com. </footer>
</div>
)
}
onSubmit(e) {
e.preventDefault();
let { username, password } = this.state;
this.props.login(username, password);
this.setState({
username: '',
password: ''
});
}
}
const mapStateToProps = (state) => {
return {
isLoginPending: state.isLoginPending,
isLoginSuccess: state.isLoginSuccess,
loginError: state.loginError
};
}
const mapDispatchToProps = (dispatch) => {
return {
login: (username, password) => dispatch(login(username, password))
};
}
export default connect(mapStateToProps, mapDispatchToProps)(LoginForm);
You need a wrapper inside your render function this solution should reolve your issue:-
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { login } from '../../redux/reducer';
import './LoginForm.css';
class LoginForm extends Component {
constructor(props) {
super(props);
this.state = {};
this.onSubmit = this.onSubmit.bind(this);
}
render() {
let { username, password } = this.state;
let { isLoginPending, isLoginSuccess, loginError } = this.props;
return (
<div className="wrapper">
<header>
<h1>Company Login</h1>
</header>
<form name="loginForm" onSubmit={this.onSubmit}>
<div className="form-group-collection">
<div className="form-group">
<label>Username/User ID:</label>
<input name="username" onChange={e => this.setState({ username: e.target.value })} value={username} />
</div>
<div className="form-group">
<label>Password:</label>
<input type="password" name="password" onChange={e => this.setState({ password: e.target.value })} value={password} />
</div>
</div>
<br />
<input type="submit" value="Login" />
</form>
<footer>Copyright © multihands.com. </footer>
</div>
);
onSubmit(e) {
e.preventDefault();
let { username, password } = this.state;
this.props.login(username, password);
this.setState({
username: '',
password: ''
});
}
}
}
const mapStateToProps = (state) => {
return {
isLoginPending: state.isLoginPending,
isLoginSuccess: state.isLoginSuccess,
loginError: state.loginError
};
}
const mapDispatchToProps = (dispatch) => {
return {
login: (username, password) => dispatch(login(username, password))
};
}
export default connect(mapStateToProps, mapDispatchToProps)(LoginForm);
If you don't need the wrapper div you can use the Fragments(https://reactjs.org/docs/fragments.html) if using React Fiber.
<React.Fragment>
<header>
<h1>Company Login</h1>
</header>
<form name="loginForm" onSubmit={this.onSubmit}>
<div className="form-group-collection">
<div className="form-group">
<label>Username/User ID:</label>
<input name="username" onChange={e => this.setState({ username: e.target.value })} value={username} />
</div>
<div className="form-group">
<label>Password:</label>
<input type="password" name="password" onChange={e => this.setState({ password: e.target.value })} value={password} />
</div>
</div>
<br />
<input type="submit" value="Login" />
</form>
<footer>Copyright © multihands.com. </footer>
</React.Fragment>

Categories

Resources