I am trying to display input value on submit. But it seems to be not working. I don't have any errors but nothing being rendered. What is wrong with the code?
import React from 'react';
import { Component } from 'react';
class App extends Component {
constructor (props) {
super(props)
this.state = {
city : ""
}
}
handleSubmit = (event)=> {
event.preventDefault();
this.setState ({
city : event.target.value
})
}
render () {
return (
<div>
<form onSubmit={this.handleSubmit}>
<input type = "text" city = "city_name" />
<button type="submit">Get Weather</button>
{this.state.city}
</form>
</div>
)
}
}
export default App;
<form
onSubmit={e=>{
e.preventDefault()
console.log(e.target[0].value)
}}>
<input type="text"/>
<button type="submit">dg</button>
</form>
that works for me very well
Remember onSubmit target:
Indicates where to display the response after submitting the form. So you can get inner elements (and their corresponding values) like normal javascript code.
const city = event.target.querySelector('input').value
handleSubmit = (event) => {
event.preventDefault();
this.setState ({ city })
}
I guess you want it to get work like below. But this is not the only way to get it done.
import React from "react";
import { Component } from "react";
class App extends Component {
constructor(props) {
super(props);
this.state = {
city: ""
};
}
handleSubmit = (event) => {
const formData = new FormData(event.currentTarget);
event.preventDefault();
let formDataJson = {};
for (let [key, value] of formData.entries()) {
formDataJson[key] = value;
}
this.setState(formDataJson);
};
render() {
return (
<div>
<form onSubmit={this.handleSubmit}>
<input type="text" name="city" />
<button type="submit">Get Weather</button>
{this.state.city}
</form>
</div>
);
}
}
export default App;
Code sandbox => https://codesandbox.io/s/eager-oskar-dbhhu?file=/src/App.js
Related
I am new to React and struggle to transform this function component into a class component with a constructor(). I can't figure out how to transform the functions happening onSubmit and onClick.
Thank you very much.
The function component:
import React, { useState, Component } from 'react';
import { render } from 'react-dom';
import './Options.css';
const Test = (props) => {
const [links, setLinks] = useState([]);
const [link, setLink] = useState('');
function handleSubmit(e) {
e.preventDefault();
const newLink = {
id: new Date().getTime(),
text: link,
};
setLinks([...links].concat(newLink));
setLink('');
}
function deleteLink(id) {
const updatedLinks = [...links].filter((link) => link.id !== id);
setLinks(updatedLinks);
}
return (
<div className="OptionsContainer">
<form onSubmit={handleSubmit}>
<input
type="text"
onChange={(e) => setLink(e.target.value)}
value={link}
/>
<button type="submit"> + </button>
</form>
{links.map((link) => (
<div key={link.id}>
<div>{link.text}</div>
<button onClick={() => deleteLink(link.id)}>Remove</button>
</div>
))}
</div>
);
};
export default Test;
When we work with class components a couple of things got changed, we have a new object this.state, a new function this.setState, you have to bind your functions on the constructor if you want to have access to this inside it. I think you'll learn way more if you read the code, so here this is your component as a class component:
import React, { Component } from 'react';
import './Options.css';
class App extends Component {
constructor() {
super()
this.state = {
links: [],
link: '',
}
this.handleSubmit = this.handleSubmit.bind(this);
}
handleSubmit(e) {
e.preventDefault();
const newLink = {
id: new Date().getTime(),
text: this.state.link,
};
this.setState({links: [...this.state.links, newLink], link: ''});
}
deleteLink(id) {
const updatedLinks = [...this.state.links].filter((link) => link.id !== id);
this.setState({...this.state, links: updatedLinks });
}
render() {
console.log(this.state)
return (
<div className="OptionsContainer">
<form onSubmit={this.handleSubmit}>
<input
type="text"
onChange={(e) => this.setState({ ...this.state, link: e.target.value})}
value={this.state.link}
/>
<button type="submit"> + </button>
</form>
{this.state.links.map((link, index) => (
<div key={link.id}>
<span>{link.text}</span>
<button onClick={() => this.deleteLink(link.id)}>Remove</button>
</div>
))}
</div>
);
}
};
export default Test;
Without seeing your original functional component, it's going to be hard to tell you what the class component should look like.
To answer your question about why onSubmit might not be working, it's because onSubmit is expecting to be passed an uncalled function, so that the <form> element can call that function itself when the time is right.
You are currently calling the function this.handleOnSubmit(), which returns nothing, so no handler for the form submit is properly assigned. Try removing the call to the function, like this:
<form onSubmit={this.handleSubmit}>
constructor() {
super();
this.state = {
name: "",
name1: "",
};
}
change = () => {
this.setState({ name: this.state.name1 });
};
handleChange = (e) => {
this.setState({ name1: e.target.value });
};
render() {
return (
<div>
<input
type="text"
placeholder="Enter your name"
onChange={this.handleChange}
></input>
<button onClick={this.change}>Click Me!</button>
<h4>Hello! {this.state.name}</h4>
</div>
);
}
This is what I did but feels like it is nonsense on actual webpage even it works. Is there a better way to take input from user?
Why you need name and name1 in state. Just name should be fine. See the below code if that helps
I am not sure why you handle a event in button. May you can use a form with OnSubmit.
import React from "react";
import "./style.css";
export default class App extends React.Component {
constructor() {
super();
this.state = {
name: "",
};
}
render() {
return (
<div>
<input
type="text"
placeholder="Enter your name"
onChange={(e) => this.setState({name: e.target.value})}
/>
<button>Click Me!</button>
<h4>Hello! {this.state.name}</h4>
</div>
);
}
}
Your onChange in the input would be
onChange={event => this.handleChange(event)}
And for the button it would be
onChange{() => this.change()}
We would not require 2 states for the name but we would need one variable to store the name and second variable to let the component know that name has been update. We need the second variable because on button click only the name has to be updated(as per the code mentioned).The component would re-render when a state is updated. Below code might be helpful.
class Content extends React.Component {
constructor(){
super()
this.state = {
name: "",
}
this.name=''
}
change = () => {
this.setState({name: this.name})
}
handleChange = (e) => {
this.name=e.target.value
}
render(){
return(
<div>
<input type = "text" placeholder="Enter your name" onChange={this.handleChange}></input>
<button onClick={this.change}>Click Me!</button>
<h4>Hello! {this.state.name}</h4>
</div>
)
}}
Here is a version with React Hooks:
import React, { useState } from 'react';
export default function App() {
const [name, setName] = useState('');
const handleNameChange = (e) => {
const nameInput = e.target.value;
setName(nameInput);
};
return (
<div>
<input
type="text"
placeholder="Enter your name"
onChange={(e) => handleNameChange(e)}
></input>
<button>Click Me!</button>
<h4>Hello! {name}</h4>
</div>
);
}
I have two components in two files: Firebase and Recipe. I call in Recipe a function createRecipe from Firebase file.
When I call this.setState({ recipies }) an error occurs. I searched a solution and tried to bind context according to results here.
Firebase file:
class Firebase {
constructor () {
app.initializeApp(config)
// TRIED
this.createRecipe = this.createRecipe.bind(this)
this.auth = app.auth()
this.db = app.database()
}
state = {
recipies: {}
}
createRecipe = recipe => {
const recipies = {...this.state.recipies}
recipies[`recipe-${Date.now()}`] = recipe
this.setState({ recipies })
}
}
export default Firebase
Recipe file:
import { withAuthorization } from '../Session'
import { withFirebase } from '../Firebase'
class Recipe extends Component {
state = {
name: '',
image: '',
ingredients: '',
instructions: ''
}
handleChange = event => {
const { name, value } = event.target
this.setState({ [name]: value })
}
handleSubmit = event => {
event.preventDefault()
const recipe = { ...this.state }
// TRIED
this.props.firebase.createRecipe(recipe)
this.props.firebase.createRecipe(recipe).bind(this)
this.resetForm(recipe)
}
render () {
return (
<div>
<div className='card'>
<form
// TRIED
onSubmit={this.handleSubmit>
onSubmit={() => this.handleSubmit>
onSubmit={this.handleSubmit.bind(this)}>
<input value={this.state.name} type='text' name='nom' onChange={this.handleChange} />
<input value={this.state.image} type='text' name='image' onChange={this.handleChange} />
<textarea value={this.state.ingredients} rows='3' name='ingredients' onChange={this.handleChange} />
<textarea value={this.state.instructions} rows='15' name='instructions' onChange={this.handleChange} />
<button type='submit'>Add recipe</button>
</form>
</div>
</div>
)
}
}
const condition = authUser => !!authUser
export default withAuthorization(condition)(withFirebase(Recipe))
Do you have an idea about what's going wrong ? Many thanks.
class Firebase doesn't extend React.component so it doesn't know what state is. This is expected, extend React.component or use state hooks useState().
You are not using react in your Firebase component
How to fix:
import React, {Component }from 'react';
class Firebase extends Component {
constructor(props){
super(props)
// your code
}
// your code
render(){
return null; // this won't change anything on your UI
}
}
I am new in React and want to develop easy app - there is input field from which I want to take values and render list. After added option in text field I want to update this list whith new option.
setState function does not work and I don't know how to connect input submit and list rendering. My code is below.
WaterApp.js
import React from 'react';
import AddWater from './AddWater';
import WaterElements from './WaterElements';
export default class WaterApp extends React.Component {
state = {
quantities: ['aaaaa', 'bbbbb', 'ccccc']
};
handleAddQuantity = (quantity) => {
this.setState(() => ({
quantities: ['ddddd', 'eeeee']
}));
console.log('works');
}
render() {
return (
<div>
<WaterElements quantities={this.state.quantities} />
<AddWater handleAddQuantity={this.handleAddQuantity} />
</div>
)
}
}
AddWater.js
import React from 'react';
export default class AddWater extends React.Component {
handleAddQuantity = (e) => {
e.preventDefault();
const quantity = e.target.elements.quantity.value;
console.log(quantity);
};
render() {
return (
<form onSubmit={this.handleAddQuantity}>
<input type="text" name="quantity" />
<input type="submit" value="Submit" />
</form>
)
}
}
WaterElements.js
import React from 'react';
const WaterElements = (props) => (
<div>
<p>Water Quantity:</p>
{
props.quantities.map((quantity) =>
<p key={quantity}>{quantity}</p>
)
}
</div>
);
export default WaterElements;
I expect list to be ddddd, eeeee at this moment.
You're never calling props.handleAddQuantity
export default class AddWater extends React.Component {
handleAddQuantity = (e) => {
e.preventDefault();
const quantity = e.target.elements.quantity.value;
props.handleAddQuantity(quantity)
};
render() {
return (
<form onSubmit={this.handleAddQuantity}>
<input type="text" name="quantity" />
<input type="submit" value="Submit" />
</form>
)
}
this.setState(() => ({
quantities: ['ddddd', 'eeeee']
}));
should be
this.setState({
quantities: ['ddddd', 'eeeee']
});
and after for add
this.setState({
quantities: [...state.quantities, quantity]
});
to update use this format
this.state({key:value});
not this.state(()=>{key:value});
handleAddQuantity = (quantity) => {
this.setState({
quantities: ['ddddd', 'eeeee']
}));
console.log('works');
}
I have the following code where someone can add names into a an array of objects. I can't get to toggle one of the elements created after submission.
import React, { Component } from 'react';
import User from './User';
class App extends Component {
constructor(props){
super(props);
this.state = {
list:list,
searchTerm:'',
userInputValue:'',
users:[],
};
}
userUpdateMethod = e =>
this.setState({
userInputValue:e.target.value
});
newUserSubmitHandler = (e) =>{
e.preventDefault();
this.setState({
users: this.state.users.concat([{name:this.state.userInputValue,isConfirmed:false}]),
userInputValue:""
});
}
toggleAttendance = () =>{
const toggleConfirmed = this.state.users.isConfirmed;
this.setState({
users:!toggleConfirmed
});
}
render() {
const {searchTerm, list} =this.state;
return (
<div className="App">
<User
a = {this.state.userInputValue}
b = {this.userUpdateMethod}
c = {this.newUserSubmitHandler}
d = {this.state.users}
e = {this.toggleAttendance}
/>
</div>
);
}
}
export default App;
The function that I can get to work is toggleAttendance and it resides on the User component
import React, { Component } from 'react';
const User = props =>
<div>
<h2>User Component</h2>
<form onSubmit={props.c}>
<input type="text" onChange={props.b} value = {props.a}/>
<button type="submit" name="submit" value="submit"> Submit</button>
</form>
<div>The follwowing will be attending:{props.d.map((user,index) =>
<div> {user.name} is {user.isConfirmed? "coming":"not coming"}
<button onClick={()=>props.e(index)}>toggle attendance</button>
</div>
)}
</div>
</div>;
export default User;
I have tried several ways to update the toggleAttendance method from the main App component but with no luck