React input can't type anything - reactjs

I have an input text and I can't write in it !
I tried to control it like that :
handleUserInput(e){
console.log('ok')
this.setState({
newPlayer: e.target.value
})
}
<input type="text" className="inputTexte" placeholder="Username" value={this.state.newPlayer} onChange={e => this.handleUserInput(e.target.value)} />
But even if I just put an input like that :
<input type="text" />
I can't write in it.
It's drive me crazy...
Do you know what I am doing wrong ?
Thanks

handleUserInput(e){
console.log('ok')
this.setState({
newPlayer: e.target.value
})
}
Most probably you have to bind this value to handler function, inside your constructor,
this.handleUserInput= this.handleUserInput.bind(this);
Or Change the handler function to fat arrow function like below
const handleUserInput = (e)=>{//write your code inside}
But before this please the check the developer console and update the error here

Define like this
handleUserInput(value){
console.log('ok')
this.setState({
newPlayer: value
})
}
because you already passed input value e.target.value
onChange={e => this.handleUserInput(e.target.value)}

You are setting state the state wrong, you are passing e.target.value to handleChange function and again using event.target.value while setting state
change your input as follows and try
<input type="text" className="inputTexte" placeholder="Username" value={this.state.newPlayer} onChange={e => this.handleUserInput(e)} />
or change handleUserInput as follows
handleUserInput(value){
console.log('ok')
this.setState({
newPlayer: value
})
}

State does update synchronously. This means that when React actually performs the update, it is at a later time and the value of the event is lost. This is because React uses a synthetic event wrapper to wrap all DOM events to ensure compatibility across all browsers and this wrapper is emptied after a while to be reused. My proposal is to simply store the event value at a variable, which will ensure it retains its value when the state update does happen.
handleUserInput(e){
console.log('ok')
const eventValue = e.target.value;
this.setState({
newPlayer: eventValue
})
}
Also, you call the function with event.target.value as parameter, and then you access the .target.value again, so it does not work.
onChange={e => this.handleUserInput(e)}
And as described above, inside handleUserInput access it via e.target.value, the way you had it previous implied that inside the function you were trying to access e.target.value.target.value.

It have a code erro, you are pass the event target value in the function but is expected the event only
try:
handleUserInput(e){
console.log('ok')
this.setState({
newPlayer: e.target.value
})
}
<input type="text" className="inputTexte" placeholder="Username" value={this.state.newPlayer} onChange={this.handleUserInput} />

Related

Array destructuring

handleChange = (event) => {
const { name, value } = event.target;
this.setState({ [name]: value });
};
Why need to use array destructuring inside setState? Since i already use {} destructuring name and value why I cannot just write this.setState({ name: value }) ?
As mentioned earlier, this method is used to handle multiple inputs. Say you have two input elements in your code:
<input name="email" onChange={handleChange} />
<input name="password" onChange={handleChange} />
When you do
this.setState({ [name]: value });
you can use a single onChange handler to update the state for both, email as well as password. This would basically translate to:
this.setState({ email: 'xyz' });
this.setState({ password: 'abc' });
If you use name instead of [name], that would basically update the name key in the state, not the input field name i.e. email & password in this case.

Change value on dynamic input fields in reactjs

I am trying to change the input value on dynamically added input fields.
Each input field value is set to a state value which is made of an array.
Seems like there should be a simple solution for this.. But I can't just figure it out.
JSfiddle:
https://jsfiddle.net/o51Lkvm6/1/
handleInputChange = (e) => {
this.setState({
[e.target.name]: e.target.value
});
}
render() {
return (
<div>
{ this.state.data.map((d, index) =>
<input name={d.Name} type="text" className="form-control"
value={d.Name} onChange={this.handleInputChange} />
)}
</div>
);
}
Update:
Is it possible to solve this without having to use defaultvalue? Since React does not recommend "Uncontrolled Components"?
First of all there are couple issues with your code:
You forgot to bind your handler method or use arrow function to
preserve this context of a class. To fix that you can either put this
in Test constructor:
this.handleInputChange = this.handleInputChange.bind(this)
or modify your existing function to:
handleInputChange = e => {};
Input value should actually use the value which
corresponds to current item from state, like that:
value={this.state.data[index]["Name"]}
Later to access proper item in your stateData you have to somehow
store that index in the input. I did this by assigning it to
data-index attribute. Also you forgot to include key prop:
<input
key={d.ID}
data-index={index}
name={d.Name}
type="text"
className="form-control"
value={this.state.data[index]["Name"]}
onChange={this.handleInputChange}
/>
In your actual handleInputChange you were not targeting the correct
thing. You need to first get the appropriate item from the array and
then modify the name. I did it by copying the actual state and later
assigning it:
handleInputChange = e => {
const stateDataCopy = this.state.data.slice();
const objectCopy = Object.assign({}, stateDataCopy[e.target.dataset.index]);
objectCopy["Name"] = e.target.value;
stateDataCopy[e.target.dataset.index] = objectCopy;
this.setState({ data: stateDataCopy });
};
Here you can find working example:
ok I fixed it for you
do these 2 things
handleInputChange(e){ make this an arrow function so it has the concept of this like so: handleInputChange = (e) => {
and use defaultValue instead of value in the input
updated fiddle for you: https://jsfiddle.net/a17gywvp/1/

Sending input value to click handler in React

I have an input number value which I'm trying to send to my clickHandler but I've done something wrong ...
On click I want to send the value "this.state.NumberHolder" to the handler
<input value={this.state.NumberHolder} onClick={this.clickHandler} type="number" />
Doing a console.log I can see that my clickHandler is being called but I'm not getting the updated state value
clickHandler = (target) => {
console.log("targetHere", target);
this.setState({
NumberHolder: target.value
});
};
Actually, what you receive by default property is the context of the event.
So, to handle correctly the value of the input tag, you need to do this:
clickHandler = (event) => {
console.log("targetHere", event.target);
this.setState({
NumberHolder: event.target.value
});
};
And there is a big issue with your JSX, onClick is executed when the input is clicked, not changed. So, you will never receive the new input value. Use on change:
<input value={this.state.NumberHolder} onChange={this.clickHandler} type="number" />
And this should work perfectly. Check this fiddle to see it working.
I believe it should be like this:
// destructure target from the event object by wrapping it in braces
clickHandler = ({target}) => {
console.log("targetHere", target);
this.setState({
NumberHolder: target.value
});
};
But there is a bigger issue with your code. Since the value of your input will always be this.state.NumberHolder, you are simply setting the same value over and over again.
If you have a particular value you want to send on the click event, you can turn your click event into a curried function like this:
// pass in number as first argument to function that returns another anonymous function
clickHandler = (NumberHolder) => () =>{
this.setState({ NumberHolder });
};
And then on the element with the click event, pass the onClick like this:
<input onClick={this.clickHandler(3)} />
That will pass the argument in scope of the function, and allow you to access it.
Considering your comments, i believe you want to add the event on change of the input and log the value entered like this:
<input value={this.state.NumberHolder} onChange={this.clickHandler} type="number" />
clickHandler = (target) => {
console.log("target Value", target.value);
this.setState({
NumberHolder: target.value
});
};

React get data attributes on html tag in onChange handler

I want to use the same onChange handler for a series of inputs.
<input onChange={this.handleInputChange}
type="text"
data-input-name="name"
value={this.state.name}/>
so I am attempting to use this html data attribute to store the input's name. When I go to pull the attribute off in JavaScript, I am unable to access it.
handleInputChange = (event) => {
this.setState([event.target.inputName]: event.target.value})
}
I've tried a few permutations to no avail, and it seems difficult to debug since when I log the event.target I just see an html element in the JavaScript console.
Any advice on how to better debug this or where my syntax is going wrong?
I've noticed that you have missed an opening curly brace in your setState call. And that will throw a syntax error when you run it. It should be fixed like this:
handleInputChange = (event) => {
this.setState({[event.target.inputName]: event.target.value})
}
For accessing your data attribute from the handleInputChange, you can do it like this:
handleInputChange = event => {
this.setState({
[event.target.getAttribute('data-input-name')]: event.target.value,
});
};
And also, you can use the default name attributes that comes with these inputs like this:
handleInputChange = event => {
this.setState({
[event.target.name]: event.target.value,
});
};
// in your render fucntion
<input
onChange={this.handleInputChange}
type="text"
name="name"
value={this.state.name}
/>
This will work as the same as using data attributes. Hope this help!
You could pass the input name as an argument instead of having it as a property, like so:
<input onChange={(e) => this.handleInputChange(e,"someValue")}
type="text"
value={this.state.name}/>
and then
handleInputChange = (event, name) => {
this.setState([name]: event.target.value})
}
I was also able to find a somewhat dirty solution to pulling the value off of the event object.
event.target.attributes['data-input-name'].value

Do not mutate state directly, Use setState() react/no-direct-mutation-state in React JS

<input
defaultValue={this.props.str.name}
ref={(input) => { this.state.name = input; }}
name="name"
type="text"
className="form-control"
onChange={this.handleInputChange}
/>
handleInputChange(event) {
this.setState({
[event.target.name]: event.target.value
});
}
if(this.state.name.value === "") {
this.msg.show('Required fields can not be empty', {
time: 2000,
type: 'info',
icon: <img src="img/avatars/info.png" role="presentation"/>
});
}
I'm trying to set the default value like that and wanted to access it as well. I did like this and accessed the value with this.state.name.value but the thing is its working but showing the warning as
Do not mutate state directly, Use setState()
react/no-direct-mutation-state .
Getting "Do not mutate state directly, Use setState()", Why?
Because, you are mutating the state value inside ref callback method to store the node ref, Here:
this.state.name = input;
Solution:
Don't use state variable to store the reference, You can directly store
them in component instance because that will not change with time.
As per DOC:
The state contains data specific to this component that may change
over time. The state is user-defined, and it should be a plain
JavaScript object.
If you don’t use it in render(), it shouldn’t be in the state. For
example, you can put timer IDs directly on the instance.
Since you are using controlled input element, ref is not required. Directly use this.state.name with input element value property and this.state.name to access the value.
Use this:
<input
value={this.state.name || ''}
name="name"
type="text"
className="form-control"
onChange={this.handleInputChange}
/>
If you wanted to use ref then store the ref directly on instance, remove value property and you can remove the onChange event also, Use it like this:
<input
ref={el => this.el = el}
defaultValue={this.props.str.name}
name="name"
type="text"
className="form-control"
/>
Now use this ref to access the value like this:
this.el.value
you can instead clone the entire property value inside the with spread operator and then reform or edit the value for example :
state = {Counters: [{id:1,value:1},{id: 2,value: 2},{id: 3,value: 3},{id: 4,value: 4}]}
increment = (Counter) => {
//This is where the state property value is cloned
const Counters = [...this.state.Counters];
console.log(Counters);
const index = Counters.indexOf(Counter)
Counters[index].value++
this.setState({
Counters: this.state.Counters
})
}
Change your line number 3 as
ref={(input) => { this.setState({name: input}); }}

Resources