how to add onchange event in react js application - javascript

I am new to reactjs I want to add onchange in my application. I am using map function for data.
onChange = (event,k,i) => {
this.setState({
dList: update(this.state.dList[k][i], {
[event.target.name]:
{$set: event.target.value}
})
})
}

state example
state = {
name:'',
password:''
}
Incase you have multiple inputs of example name and password
<input type="text" name="name" value={name} onChange={this.handleChange} />
<input type="password" name="password" value={password} onChange={this.handleChange} />
this how you apply the onchange handler
handleChange = e => {
this.setState({[e.target.name]: e.target.value})
}

You should put an onChange function in a onChange html tag attribute.
Example:
<input type="text" value={this.state.value} onChange={this.handleChange} />
Reference

If you want to update your component's state which depends on the previous state of the component, use the overloaded version of setState which takes a function as a parameter. This is because the calls made to the setState function are batched to improve performance.
onChange = (event,k,i) => {
this.setState(prevState => {
dList: update(prevState.dList[k][i], {
[event.target.name]:
{$set: event.target.value}
})
})
}

Related

How to Change pre filled input values

I new to React. I have two input fields which are filled when the pages loads via axios but when I want to change the Values I am unable to change them even I can not type anything on them.
function MainView() {
const [InputFields, setInputFields] = useState({
name: "",
fullURL: "",
});
const changeHandler = (e) => {
setInputFields({
...InputFields,
[e.target.name]: e.target.value,
});
};
const [links, setLinks] = useState([]);
const getLinks = () => {
axios.get('../sanctum/csrf-cookie').then(response => {
axios.get("/userlinks/getdata").then((res) => {
console.log(res);
setLinks(res.data);
}).catch((err) => {
console.log(err);
});
});
};
useEffect(() => {
getLinks();
}, []);
return (<div>
{links.map((link) => {
return (<div className="card" key={link.id}>
<form>
<input className="form-control" value={link.name} type="text" name="name" placeholder="name" onChange={changeHandler} />
<input className="form-control" value={link.fullURL} type="text" name="fullURL" placeholder="fullURL" onChange={changeHandler} />
</form>
</div>);
})}
</div>
);
}
export default MainView;
This happens because in your onChange method, you are changing InputFields variable, where as your getLinks method changes links variable, which is being rendered on the screen.
If you want to set an initial value, and then allow the user to change it, change your input to :
<input className="form-control" defaultValue={link.name}
value={InputFields.name} type="text" name="name" placeholder="name" onChange={changeHandler} />
Likewise change for your other input, if you do not want the user to change the value later on, it's often better to add disable in the input to avoid confusing people. 🙂
I know that this has been done so that you can create a minimal reproducible example for us, but I would have directly called setInputFields in the axios.get section to avoid this problem in the first place, however, if not possible, use the defaultValue and value as I've shown above.

setState not working properly when using value={} in input field

I am using React JS.
I am setting the state, however, there is a problem, in the value={} part of the input field.
Here is my code:
import React from 'react';
class SomeClass extends React.Component{
constructor(props){
super(props);
this.state = {
passCode: {
email: "Email",
password: "Password"
},
errorMessage: ''
};
}
handleChange = (event) =>{
console.log(`input detected`);
let request = Object.assign({},this.state.passCode);
request.email = event.target.value;
request.password = event.target.value;
this.setState({passCode: request});
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<label>Email Address</label>
<input type="text" value={this.state.passCode.email} onChange={this.handleChange} placeholder="Enter Email Address" />
<label>Password</label>
<input type="password" value={this.state.passCode.password} onChange={this.handleChange} placeholder="Enter One Time Password" />
<Button type="submit">
Sign In</Button>
</form>
);
}
}
export default SomeClass;
My Question:
I have is for the value attribute of the input fields, I think setState is not working properly:
In the passCode object of the state.
When I type the email, both fields get set to what I typed in the email field.
When I type the password, both fields get set to what I typed in the password field.
What's the reason for such problem?
setState is working properly; your handleChange isn't. You're setting both email and password to the value of the input regardless of which input the change occurred on. Instead, you want to update just the relevant property. To do that, I'd add name attributes to the input elements (name="email" and name="password"), then:
handleChange = ({currentTarget: {name, value}}) =>{
console.log(`input detected`);
this.setState(({passCode}) => {
return {passCode: {...passCode, [name]: value}};
});
};
Key bits there are:
It only updates the property the change related to, keeping the other one unchanged, by using the name of the input.
It uses the callback version of setState (best practice since we're setting state based on existing state).
Your funtion handleChange is wrong. You should update like this with using name:
handleChange = (event) => {
console.log(`input detected`);
const { name, value } = event.target;
this.setState({ passCode: { ...this.state.passCode, [name]: value } });
};
And set name to input:
<input type="text" value={this.state.passCode.email} onChange={this.handleChange} placeholder="Enter Email Address" name="email" />
<input type="password" value={this.state.passCode.password} onChange={this.handleChange} placeholder="Enter One Time Password" name="password" />
The methods they gaved are good, but I still suggest that you separate the methods of changing the two, maybe it will be much better.

React DOM not re-rendering accordingly to setState

I am working on a part of a React application where a todo can be created, with the following JSX code:
<form>
<div>
<label htmlFor="subject">Subject: </label>
<input type="text" value={todo.subject} onChange={e => handleInput(e, 'subject')} name="subject" id="subject"></input>
</div>
<div>
<label htmlFor="duedate">Due date: </label>
<input type="date" value={todo.duedate} onChange={e => handleInput(e, 'duedate')} name="duedate" id="duedate"></input>
</div>
<div>
<label htmlFor="description">Description: </label>
<textarea value={todo.description} onChange={e => handleInput(e, 'description')} name="description" id="description"></textarea>
</div>
<div>
<label htmlFor="sidenote">Sidenotes: </label>
<textarea value={todo.sidenote} onChange={e => handleInput(e, 'sidenote')} name="sidenote" id="sidenote"></textarea>
</div>
<button type="submit" onClick={e => handleSubmit(e)}>Submit</button>
</form>
The todo state and handleInput are defined as follows:
const [todo, setTodo] = useState({
'subject': '',
'duedate': '',
'description': '',
'sidenote': ''
});
const handleInput = (e, field) => {
e.persist();
setTodo(prevTodo => {
prevTodo[field] = e.target.value;
return prevTodo;
});
}
By running console.log(todo) after input changes, I can confirm that the state updates properly; however, these state changes are not rendered as the value for the input elements. Conversely, changing handleInput to the following solved the problem:
const handleInput = (e, field) => {
e.persist();
setTodo(prevTodo => {
let newTodo = {...prevTodo};
newTodo[field] = e.target.value;
return newTodo;
});
}
Considering that both functions correctly updated the todo state, what has caused the latter function to work but not the former one?
Generally, in your case you have to return a shallow copy object rather than just modify the key of the current reference state since React won't compare deep in key, it just compares by === to check if current state & next state is different then decide to re-render or not, you can also re-write to be working also:
const handleInput = (e, field) => {
e.persist();
setTodo(prevTodo => {
return {
...prevTodo,
[field]: e.target.value,
}
});
}

how to reset the value of fields without using refs in reactjs?

I am new to react and i think it is a silly question to ask but then too
I have a generic input component of text field in which i haven't passed refs and i want to reset the value of text field on button click? Is it possible to clear the value of field on click without passing refs?
handleClick : function(change){
change.preventDefault();
var self=this;
if(this.state.newpwd === this.state.cfmpass){
var pass = {"pwd":self.state.newpwd};
var url = "xyz"
Request.PatchRequest(url,pass,function(response){
self.setState({
authMsg : JSON.parse(response.response).data
});
now how to clear the field value here??
<TextBox type="password"
name="password"
placeholder="Enter new password"
onChange={this.changePwd} />
this is my button on which i want to perform check (which i have done) and after response i want to clear the field value
<Button type="button"
value="Change"
onClick={this.handleClick}/>
TextBox is my generic component..
Any help will be very thankful.
Thank you in advance :)
You will need a component's prop that 'control' the input's value with onChange function. You'll need to do some steps:
Add inside your constructor method the input's value initial state, most cases uses a empty string
Make your onChange function set a new state for that value
Do not forget to bind your function inside constructor
For even more details, you can copy and paste your components code, to confirm your react syntax (es5, es6 or es7)
Example:
constructor() {
this.state: {
value: ''
this.changePwd = this.changePwd.bind(this)
}
changePwd(event) {
this.setState({ value: event.target.value })
}
<TextBox
type="password"
name="password"
placeholder="Enter new password"
value={this.state.value}
onChange={this.changePwd}
/>
This approach assumes the parent component (the thing that holds both the textarea and the button) is maintaining the state of the textarea (which in this case, would be the way to do it)
// somewhere within the component (probably the container component)
reset() {
this.setState({ value: '' });
}
onChange(e) {
this.setState({ value: e.target.value });
}
// render
<TextBox
type="password"
name="password"
placeholder="Enter new password"
onChange={this.onChange}
value={this.state.value}
/>
<button onClick={this.reset}>reset</button>
EDIT Updated based on an updated question...
constructor(props) {
super(props);
this.change = this.change.bind(this);
this.inputOnChange = this.inputOnChange.bind(this);
}
change(e) {
e.preventDefault();
if(this.state.newpwd === this.state.cfmpass) {
var pass = {
"pwd": this.state.newpwd
};
var url = "xyz";
Request.PatchRequest(url, pass, (response) => {
this.setState({
authMsg : JSON.parse(response.response).data,
value: '',
});
});
}
inputOnChange(e) {
this.setState({ value: e.target.value });
}
// render
render() {
return (
<TextBox
type="password"
name="password"
placeholder="Enter new password"
onChange={this.inputOnChange}
value={this.state.value}
/>
<button onClick={this.change}>Change</button>
);
}

Passing extra argument to onChange Listener in reactjs

I see that an onChange listener usually doesn't have extra arguments other than e.
handleOnChange(e) {
this.setState({email: e.target.value});
}
But is it still possible to pass extra arguments? Like this:
handleOnChange(e,key) {
this.setState({[key]: e.target.value});
}
I modified the code from this thread to make an example
class FormInput extends React.Component{
consturctor(props){
super(props);
this.state = {email:false,password:false}
}
handleOnChange(e,key) {
this.setState({[key]: e.target.value});
}
render() {
return
<form>
<input type="text" name="email" placeholder="Email" onChange={this.handleOnChange('email')} />
<input type="password" name="password" placeholder="Password" onChange={this.handleOnChange('password')}/>
<button type="button" onClick={this.handleLogin}>Zogin</button>
</form>;
}
}
A few ways to do this:
Add an attribute/or access the attribute from the element
Using this code:
class FormInput extends Component{
onChange(e) {
const { target } = e;
const key = target.getAttribute('name');
}
}
Bind the extra attribute (partials) when you create the onChange function
Using this code:
<input name='password' onChange={this.onChange.bind('password')} />
//or
<input name='password' onChange={(e) => this.onChange('password',e)} />
Do note that you would need to change the order of the onChange function
onChange(key,e) {
//key is passed here
}
This is usually not advisable because you would create the function on each render call. See if its fine on your case
List item
Lastly you can wrap the element and from there just pass what the caller needs on the onChange
class Input extends Component {
dispatchOnChange(e) {
const { props } = this;
const { name } = props;
const value = e.target.value;
props.onChange(name,value);
}
render() {
return <input {...this.props} onChange={this.dispatchOnChange}/>
}
}
//your render
<Input type="password" name="password" placeholder="Password" onChange={this.handleOnChange}/>
Hope this helps
You could create an anonymous function, calling handleOnChange with your custom key. That would look like:
<button type="button" onClick={(e) => this.handleLogin(e, index)}>
If you have not worked with anonymous functions before, this is telling JavaScript to create a new function on the fly during render, that takes a parameter e and calls this.handleLogin(e, index). In JavaScript, anonymous functions inherit scope, so the "this" keyword will be scoped correctly.

Categories

Resources