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

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)])

Related

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;

Why css file of one component interacted with the css file of another component in ReactJS? How to handle it?

I am trying to make a website template with Reactjs. In the Jumbotron section i make subscription form and in the home section User Entry form. But the css of one component interacted with another's one. How can i handle it?
[1]: https://i.stack.imgur.com/Wd4OQ.png
User EntryJs:-
import React, { Component } from 'react'
import './User Entry.css'
class Form extends Component {
initialState = {
name: "",
age: "",
job: ""
}
state = this.initialState
changeHandler = event => {
const { name, value } = event.target
this.setState({
[name]: value
})
}
render() {
const { name, job, age } = this.state
return (
<form className="form-inline">
<div className="row">
<div className="col-md-3">
<div className="form-group">
<label htmlFor="name">Name:-</label>
<input type="text"
className="form-control"
name="name"
id="name"
value={name}
autoFocus
onChange={this.changeHandler} />
</div>
</div>
<div className="col-md-3">
<div className="form-group">
<label htmlFor="age">Age:-</label>
<input type="text"
className="form-control"
name="age"
id="age"
value={age}
autoFocus
onChange={this.changeHandler} />
</div>
</div>
<div className="col-md-3">
<div className="form-group">
<label htmlFor="job">Job:-</label>
<input type="text"
className="form-control"
name="job"
id="job"
value={job}
autoFocus
onChange={this.changeHandler} />
</div>
</div>
<div className="col-md-3"></div>
</div>
</form>
)
}
}
export default Form
Header JS:-
import React, { Component } from 'react'
import './Header.css'
import { Link, withRouter } from "react-router-dom";
class Header extends Component {
constructor(props) {
super(props)
this.state = {
email: ""
}
}
submitHandler = event => {
event.preventDefault();
alert(`Subscribed Email is : ${this.state.email}`);
}
changeHandler = event => {
this.setState({
email: event.target.value
})
}
render() {
return (
// Navbar Starts
<div>
<div className="row navbar">
<Link to="/" style={{textDecoration:'none'}}><div className="col-md-2 logo">ReactApp</div></Link>
<div className="col-md-6"></div>
<Link to="/" style={{textDecoration:'none'}}> <div className="col-md-1 link"> Home</div> </Link>
<Link to="/about" style={{textDecoration:'none'}}> <div className="col-md-1 link"> About</div> </Link>
<Link to="/counter" style={{textDecoration:'none'}}> <div className="col-md-1 link"> Counter </div></Link>
<Link style={{textDecoration:'none'}}><div className="col-md-1 link">Login</div></Link>
</div>
<div className="jumbotron text-center">
<h1>React-App</h1>
<p>We specialize in <strong>Web Development</strong></p>
{/* Subscribing form starts*/}
<form className="form-inline subscribingForm" onSubmit={this.submitHandler}>
<div className="input-group">
<input type="email"
className="form-control"
value={this.state.email}
onChange={this.changeHandler}
size="80"
placeholder="Email..."
required />
<div className="input-group-btn">
<input type="submit" value="Subscribe" className="subscribingBtn" />
</div>
</div>
</form>
{/* Subscribing form closes*/}
</div>
</div>
)
}
}
export default withRouter(Header);
Where is the .css file loaded, in the root component? It probably is loaded globally and is used on every component.Better use JSS (https://cssinjs.org/?v=v10.3.0)
In general react transpiles all the css and add it in to tag.
And as result you one file css conflicts with other.
If you want to avoid this, you can use modular css.
https://create-react-app.dev/docs/adding-a-css-modules-stylesheet/

this.props.onAdd is not a function?

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>
)
}
}
``````````````````````````````````````````````````````````````````````````````````````````````

React undefined this in function

someone can explain to me why this value in the renderInput function is undefined. I browse the code and everything looks good.
Here is error
Uncaught TypeError: Cannot read property 'renderError' of undefined
This is my component AddCatalog. When it calls console.log(this) in renderInput, this returns me undefinded
import React, {PropTypes} from "react";
import {Field, reduxForm} from "redux-form";
//
class AddCatalog extends React.Component {
constructor(props) {
super(props);
this.renderError = this.renderError.bind(this);
}
renderError({error, touched}) {
alert("asds");
if (touched && error) {
return <div className="red">{error}</div>;
}
}
renderInput({input, label, meta}) {
return (
<div className="form-group">
<label>{label}</label>
<input {...input} className="form-control" autoComplete="off" />
{this.renderError}
</div>
);
}
onSubmit(formValues) {
console.log(formValues);
}
render() {
return (
<form onSubmit={this.props.handleSubmit(this.onSubmit)}>
<div className="row paddingLR30 container-fluid">
<div className="col-12">
<h2>Dane placówki</h2>
</div>
<div className="col-3">
<Field label="Nazwa placówki*" name="name_kindergarten" component={this.renderInput} />
</div>
</div>
<button>Submit</button>
</form>
);
}
}
const validate = (formValues) => {
const errors = {};
if (!formValues.name_kindergarten) {
errors.name_kindergarten = "Musisz podać nazwę przedszkola";
}
return errors;
};
export default reduxForm({
form: "simple",
validate
})(AddCatalog);
Instead of calling this function like this.renderError() , you gave a pointer like this.renderError.
present code :
renderInput({input, label, meta}) {
return (
<div className="form-group">
<label>{label}</label>
<input {...input} className="form-control" autoComplete="off" />
{this.renderError}
</div>
);
}
correct code :
renderInput({input, label, meta}) {
return (
<div className="form-group">
<label>{label}</label>
<input {...input} className="form-control" autoComplete="off" />
{this.renderError()}
</div>
);
}
Because renderInput is not called in the context of the component - you forgot to bind it to this in the constructor the way you did with renderError.

Keep code DRY on create/edit form

I have a few inputs that are used in my form for both create and update. I decided to make them a component.
// used for CRU on the event record
import React from 'react';
class Form extends React.Component {
render() {
return (
<div className="slds-form">
<div className="slds-form-element">
<label className="slds-form-element__label">Assigned To</label>
<div className="slds-form-element__control">
<input ref={(input) => this.assigned = input} type="text" className="slds-input" disabled/>
</div>
</div>
<div className="slds-form-element">
<label className="slds-form-element__label">Related To</label>
<div className="slds-form-element__control">
<input ref={(input) => this.related = input} type="text" className="slds-input" disabled/>
</div>
</div>
<div className="slds-form-element">
<label className="slds-form-element__label">Location</label>
<div className="slds-form-element__control">
<input ref={(input) => this.location = input} type="text" className="slds-input" />
</div>
</div>
<div className="slds-form-element">
<label className="slds-form-element__label">Event Start</label>
<div className="slds-form-element__control">
<input ref={(input) => this.start = input} type="text" className="slds-input" />
</div>
</div>
<div className="slds-form-element">
<label className="slds-form-element__label">Event End</label>
<div className="slds-form-element__control">
<input ref={(input) => this.end = input} type="text" className="slds-input" />
</div>
</div>
<div className="slds-form-element">
<label className="slds-form-element__label">Contact</label>
<div className="slds-form-element__control">
<input ref={(input) => this.contact = input} type="text" className="slds-input" disabled/>
</div>
</div>
<button type="button" className="slds-button slds-button--neutral">Cancel</button>
<button type="submit" className="slds-button slds-button--brand">{this.props.buttonLabel}</button>
</div>
);
}
}
export default Form;
I then attempted to use this component in my <Create /> component.
// used for Create on the event record
import React from 'react';
import Form from './Form';
class Create extends React.Component {
createEvent(e) {
console.log("createEvent() has fired.");
e.preventDefault();
const event = {
assigned: this.assigned.value,
related: this.related.value,
location: this.location.value,
start: this.start.value,
end: this.end.value,
contact: this.contact.value
}
console.log(event);
}
render() {
return (
<form onSubmit={(e) => this.createEvent(e)}>
<Form buttonLabel="Create" />
</form>
);
}
}
export default Create;
When I try to hit the Create button on my <Create /> component I get an error
Uncaught TypeError: Cannot read property 'value' of undefined
at Create.createEvent (webpack:///./src/components/Event/Create.js?:42:32)
at onSubmit (webpack:///./src/components/Event/Create.js?:59:27)
at Object.ReactErrorUtils.invokeGuardedCallback (webpack:///./~/react/lib/ReactErrorUtils.js?:70:16)
at executeDispatch (webpack:///./~/react/lib/EventPluginUtils.js?:89:21)
at Object.executeDispatchesInOrder (webpack:///./~/react/lib/EventPluginUtils.js?:112:5)
at executeDispatchesAndRelease (webpack:///./~/react/lib/EventPluginHub.js?:44:22)
at executeDispatchesAndReleaseTopLevel (webpack:///./~/react/lib/EventPluginHub.js?:55:10)
at Array.forEach (native)
at forEachAccumulated (webpack:///./~/react/lib/forEachAccumulated.js?:25:9)
at Object.processEventQueue (webpack:///./~/react/lib/EventPluginHub.js?:231:7)
I then check the console and see the refs belong in my <Form /> component, and not my <Create /> component.
Is there a way to pass the refs from my child component, <Form />, to its parent, <Create />?
That's a lot of refs! Good news, you really don't need them, at all. As a very very general rule, you should only be using refs if you are interacting with an external library that doesn't "understand" React (d3, Greensock, TinyMCE, etc).
Tackling it in an uncontrolled way can be done like:
const User = (props) => (
<div>
<input name="foo" className="form-control" />
<input name="foo2" className="form-control" />
<button type="submit" className="btn btn-primary">{props.buttonLabel}</button>
</div>
);
class App extends React.Component {
constructor(props) {
super(props);
this.onChange = this.onChange.bind(this);
this.onSubmit = this.onSubmit.bind(this);
}
onChange(e) {
this.setState({
[e.target.name]: e.target.value,
});
}
onSubmit(e) {
e.preventDefault();
console.log(this.state);
}
render() {
return (
<div className="container">
<br />
<form onChange={this.onChange} onSubmit={this.onSubmit}>
<User buttonLabel="Create"/>
</form>
</div>
);
}
};
ReactDOM.render(<App />, document.getElementById('app'));
Codepen example:
http://codepen.io/cjke/pen/zNXxga?editors=0010

Categories

Resources