LifeCycle of onChange in react - javascript

I am writing a simple react application, now I am working on an element that can take the user's input. I have been very curious about the order of the execution of line of code inside the onChange() function. So I added a little print statement to see how exactly things are changed.
Here's my code
function CreateReview() {
const [input, setInput] = useState({
title:'',
content:''
})
useEffect(() => {
console.log('render');
},[input])
function handleChange(event){
const {name, value} =event.target;
console.log(1)
setInput(prevInput=>
{
console.log(2)
return{
...prevInput, //...prevInput is to reserve the last Input
[name]: value //name is dynamic, "title" then setTitle, "content" then setContent.
}
}
)
console.log(3)
console.log(event.target);
}
function handleClick(event){
event.preventDefault();
console.log(input);
}
return <div className = "container">
<h1>Create Review</h1>
<form>
<div className="form-group">
<input onChange={handleChange} name="title" value={input.title} autoComplete="off" className = 'form-control' placeholder="Your Name"></input>
</div>
<div className="form-group">
<textarea onChange={handleChange} name="content" value={input.content} autoComplete="off" className = 'form-control' placeholder="Review Content"></textarea>
</div>
<button onClick={handleClick} className="btn btn-large btn-info">Add Note</button>
</form>
</div>
}
export default CreateReview;
And here's the output console
Console screenshot
I wonder why it goes 1,3,2. is there any reason behind it?

Kindly go to react document to read more about how state works in react.
As far as your concerned useState or setState are the async events, so whenever you are try to call them it will execute later rather do synchronously(line by line).

Related

To Do list updates an empty string in the list

I have started an internship I have to build a to-do list using NEXT JS. but the problem arises that the app also updates an empty string. I have to work on this and have more than 20 hours to dig up a solution. I wasn't able to solve it. I tried passing some parameters but it's not working.
import { useState } from "react"
import '../styles/globals.css'
const index=()=> {
const [userinput,setuserinput]=useState("")
const [todolist,settodolist]=useState([])
const handlechange=(e)=>{
e.preventDefault()
if(e.target.value!=""){
setuserinput(e.target.value)
}
}
const handlesubmit=(e)=> {
settodolist([
userinput,
...todolist
])
e.preventDefault()
}
const handledelete=(todo)=>{
const updatedelete=todolist.filter(todoitem => todolist.indexOf(todoitem) != todolist.indexOf(todo))
settodolist(updatedelete)
}
return(
<div className="FLEX">
<h3 className="heading">Welcome to Next JS To Do app</h3>
<form className="FORM">
<div className="Wrap">
<input type="text" onChange={handlechange} placeholder="Enter a todo item" className="INPUT"></input>
<button onClick={handlesubmit} className="Button">Submit</button>
</div>
</form>
<ul>
{
todolist.length>=1?todolist.map((todo,idx)=>{
return <li key={idx}>{todo} <button onClick={(e)=>{
e.preventDefault()
handledelete(todo)
}}>Delete</button></li>
}):"Enter a Todo List"
}
</ul>
</div>
)
}
export default index
You need to pass the value prop to your input element:
<input type="text" value={userinput} onChange={handlechange} placeholder="Enter a todo item" className="INPUT"></input>
If you don't want the user to submit an empty item to the todo list, check if the userinput is empty or not.
const handlesubmit = (e) => {
if (userinput === "") return
settodolist([
userinput,
...todolist
])
e.preventDefault()
}
I believe the question is asking to prevent the user from entering a todo item with no name. In this case, do as the previous comment mentioned and add the value prop to the input:
<input type="text" value={userinput} onChange={handlechange} placeholder="Enter a todo item" className="INPUT"></input>
then add this to your handleSubmit function:
const handlesubmit = (e) => {
e.preventDefault();
if (userinput != '') {
settodolist([userinput, ...todolist]);
}
};

How to submit the same form multiple times in React

I have a react app that requires the same form(s) to be submitted multiple times.
Below is my code for the control panel class.
The values are entered into separate forms, and the button is pressed, sending the form input field values to another component for processing. After this is done, I would like to be able to re-submit the form (eg: simply click the button again) and for the processing to start over.
The formSubmit field (in this.state) is set to false initially, but set to true when the form is submitted. Once this is done, the {this.state.formSubmit && } line (near the end) ensures that the processing starts when the formSubmit value is set to true. Once the processing is done, I assume that simply setting the formSubmit value to false again will allow for the form to be submitted again, but I do not yet know how to do this.
class App extends React.Component {
constructor(props) {
super(props);
this.state = { BO_course: "",
BO_max_speed: "",
formSubmit: false
};
this.handleInput = this.handleInput.bind(this);
this.handleFormSubmit = this.handleFormSubmit.bind(this);
}
handleInput (event) {
const value = event.target.value;
console.log(value);
this.setState({
...this.state,
[event.target.name]: value,
});
}
handleFormSubmit (event) {
console.log("Submitting form");
event.preventDefault();
this.setState({formSubmit: true});
// this.setState({formSubmit: false})
}
render () {
return (
<div className="App">
<div className="container">
<form onSubmit={this.handleFormSubmit}>
<label className="name">
Name
<input className="inputstyleright"
type="text"
name="nameinput"
onChange={this.handleInput}
/>
</label>
</form>
<form onSubmit={this.handleFormSubmit}>
<label className="surname">
Surname
<input className="inputstyleright"
type="text"
name="surnameinput"
onChange={this.handleInput}
/>
</label>
<input className="submitbutton" type="submit" value="Submit"/>
</form>
<div className="topleft">Control Panel</div>
<div className="square"></div>
</div>
{/* only evaluates to true if the form has been submitted */}
{this.state.formSubmit && <RM search1={this.state} />}
</div>
);
}
}
export default App;
I managed to solve it by updating the button to use an onClick function:
<input className="submitbutton" type="submit" value="Submit" onClick={()=>getRM(this.state)}/>
and changing
{this.state.formSubmit && <RM search1={this.state} />}
to just
{<RM />}
I also moved the function I was calling in the
<RM search1={this.state} />
part outside of the RM class itself. The function is now called by the onClick in the button eg: "getRM()"

What is the error in this code of react? When i call the function in part 1 it doesnt work but part 2 works

This is my code. when i use function in part 1 it shows nothing on console. but when i use function in part 2 it shows 'Hello'. but i cant see any differences. What am i doing wrong in part 1?
handleChange = (e) => {
this.setState({
[e.target.id]:e.target.value
})
}
// part 1
handleSubmit = (e) => {
e.prevendDefault()
console.log(this.state)
console.log("hello")
}
// part 2
handleSubmit = (e) => {
e.preventDefault();
console.log(this.state)
console.log('hello')
}
render() {
return (
<div className="form-group container w-50">
<form onSubmit={this.handleSubmit}>
<label htmlFor="">Email</label>
<input type="email" id="email"className="form-control" onChange={this.handleChange} />
<label htmlFor="">Password</label>
<input type="password" id="password" className="form-control" onChange={this.handleChange}/>
<button type="submit" className="btn btn-primary" >Submit</button>
</form>
</div>
);
}
There is a spelling mistake
handleSubmit = (e) => {
e.prevendDefault()
console.log(this.state)
console.log("hello")
}
it's preventDefault() but you had prevendDefault.
I would suggest using an IDE or editor with IntelliSense or autocomplete feature to prevent these kinds of mistakes in the future.

React: generating input field data with a button component

I'm creating an intake form where a piece of data can be input into the text field, or generated randomly with a button next to the field.
I want to do this for 3 fields on the form so I created a component
called <RandomDataButton />
I'm stuck with how to make sure the results of the calculation done by the button component update the value of the text box so that the form submission contains the generated data.
I don't fully understand the state propagation, but what I do understand is that the flow is one way, down the hierarchy of components.
So what I am attempting to do is have a choice of inputting some data in the text box, or generating some random data from a button (I'd like to reuse it in other ui creations)
Where I am stuck is how do I update the input field from the componenet that is lower in the hierarchy.
Do I pass the state to the randomizer button and then have it update a copy of state? Or am I totally off base with that approach?
App:
class App extends React.Component {
render(){
return (
<div>
<DataInputForm />
</div>
);
}
}
DataInputForm:
class DataInputForm extends React.Component{
state= {
projectname: '',
datasource: '',
data1: '',
data2: '',
data3: '',
};
handleSubmit = e => {
e.preventDefault();
console.log({
projectname: this.projectname.value,
datasource: this.datasource.value,
data1: this.data1.value,
data2: this.data2.value,
data3: this.data3.value,
});
}
handleChange = e => this.setState({[e.target.name]: e.target.value});
render(){
return(
<form className="ui form" onSubmit={this.handleSubmit}>
<div className="field">
<label htmlFor="projectname">Project Name: </label>
<input
type="text"
id="projectname"
name="projectname"
placeholder="Project Name"
ref={input => this.projectname = input}
/>
</div>
<div className="field">
<label htmlFor="datasource">Data Source: </label>
<input
type="text"
id="datrasource"
name="datasource"
placeholder="Data Source"
ref={input => this.datasource = input}
/>
</div>
<div className="field">
<label htmlFor="data1">Data 1: </label>
<input
type="number"
min="3"
max="18"
id="data1"
name="data1"
ref={input => this.data1 = input}
/>
<RandomDataButton buttonid={"data1button"} buttonname={"Data1"} />
</div>
<div className="field">
<label htmlFor="data2">Data 2: </label>
<input
type="number"
min="3"
max="18"
id="data2"
name="data2"
ref={input => this.data2 = input}
/>
<RandomDataButton buttonid={"data2button"} buttonname={"Data2"} />
</div>
<div className="field">
<label htmlFor="data3">Data 3: </label>
<input
type="number"
min="3"
max="18"
id="data3"
name="data3"
ref={input => this.data3 = input}
/>
<RandomDataButton buttonid={"data3button"} buttonname={"Data3"} />
</div>
<button className="ui button" type="submit">Create Data</button>
</form>
);
}
}
RandomDataButton:
const getRandom = max => Math.floor(Math.random() * Math.floor(max));
class RandomDataButton extends React.Component {
generateData(value){
var result, destination;
destination = value.toLowerCase();
result = getRandom(1000);
console.log("Generated " + result + " for range of " + value + "]: " + destination);
//this.state.{destination};
}
render(){
return(
<button id={this.props.buttonid} type="button" onClick={this.generateData.bind(null,this.props.buttonname)}>{this.props.buttonname}</button>
//<button id="strbutton" type="button">Generate</button>
);
}
}
Pass a function as prop to RandomDataButton. Define the function in DataInputForm and use it update the state in DataInputForm by calling the prop function from RandomDataButton whenever you need the update.
It seems you are working with multiple components, so while working with multiple components, it is highly recommended to use any central storage container, which would be useful to get your desired data in any components
Flux and redux both are tested architectures for data state management, you could use any of them, I would recommend using redux.
Here's a codesandbox for your reference: https://codesandbox.io/s/bold-frog-01ff2
This is effectively a continuation of Amala's suggestion.
You are correct, the hierarchy is one-way. Which means we should define a function in DataInputForm (lvl2) and pass it as a prop to RandomDataButton (lvl3). That function is bound to DataInputForm's execution context, and we want to update it's state so we can feed the new data back into each individual input.
For example:
createRandomText = (associatedField, value) => {
this.setState(
{
[associatedField]: value
},
() => console.log(this.state)
);
};
So to update the state correctly, we need to provide a field corresponding to the right input, and a value (the randomized value).
We pass in that function as a prop to RandomDataButton and use it for the onClick() handler.
class RandomDataButton extends React.Component {
generateData = () => {
let result = getRandom(1000);
this.props.createRandomText(this.props.matchingInput, result);
};
render() {
return (
<button
id={this.props.buttonid}
type="button"
onClick={this.generateData}
>
{this.props.buttonname}
</button>
//<button id="strbutton" type="button">Generate</button>
);
}
}
Additionally we need to provide another prop to the button component so we can call the above function correctly:
<RandomDataButton
buttonid={"data1button"}
buttonname={"Data1"}
createRandomText={this.createRandomText}
matchingInput={"data1"}
/>
See sandbox for full details :)

Getting value of input in React and checking it

I have an input field and a button. I want to make so that if a user enters a value in the input field that is a number when he clicks the button a div with information should appear. Right now when the button is clicked it loads my data, but it works even if the input is empty. How can I properly get the value from the input, check if its a number and if it is indeed a number the div should display the info, here is what I made so far:
class CardCheck extends Component {
constructor(props) {
super(props);
this.state = { showMessage: false };
}
_checkValue() {
if (evt.taget.value != number) {
this.setState(prevState => ({
showMessage: !prevState.showMessage
}));
} else {
alert("Your card id can consist only of numbers!")
}
}
_showMessage = () =>
this.setState(prevState => ({
showMessage: !prevState.showMessage
}));
render() {
return (
<div>
<div className="newsletter-container">
<h1>Enter the ID of your card:</h1>
<div className="center">
<input type="number" onChange={(evt) => { console.log(evt.target.value)}} />
<input type="submit" value="Check" onClick={this._showMessage {this._checkValue} />
</div>
<div />
{this.state.showMessage && (
<div className="results">
<h2 className="green-heading">Your card is valid in the following places:</h2>
<p>Magic Auto Spa</p>
<p>Ivans auto shop</p>
<p>AutoHouse Sofia</p>
<p>Bankya Auto Palace</p>
<button className="close" onClick={this._showMessage}>
Close
</button>
</div>
)}
</div>
<h1>Offers:</h1>
</div>
);
}
}
export default CardCheck;
I tried obtaining the value with the onChange event, check it's type with an if statement and attach that event as a second onClick but it does not work
You have a typo in your code:
_checkValue() {
if (evt.taget.value != number) {
// -------^ should be target
Also, Number.isNaN would be a more robust comparison.
First, you have an error in
<input type="submit" value="Check" onClick={this._showMessage{this._checkValue} />
Next,
<input> Boxes in React works a little bit differently.
Check out this link

Categories

Resources