React Binding and Populating an Object - reactjs

I have a React Component which maintains a Local State as shown below:
this.state = {
user : {}
}
I have 2 textboxes on the screen where I can enter name and age. I am sending the values from the textboxes and populating the user object inside the state as shown below:
onTextBoxChange = (e) => {
// this.user is a property on the Component declared inside the // constructor
this.user[e.target.name] = e.target.value
this.setState({
user : this.user
})
}
Is there a better way of populating the state with the user object which consists of name and age.

There is no need to create an extra variable (let user =...) or a member variable (this.user).
Just overwrite previous values using spread syntax.
onTextBoxChange = e => {
this.setState({
user: {
...this.state.user,
[e.target.name]: e.target.value
}
});
};
Here is the fully working version on CodeSandBox.

You can achieve the same by following three different ways:
1) There's no need to creating an this.user property, instead to can achieve the same by using a local variable. So, the function can be changed to:
onTextBoxChange = (e) => {
let user = this.state.user;
user[e.target.name] = e.target.value;
this.setState({
user: this.user
})
}
2) If you're not using user state in input text boxes for value, then you can simply use this.user property instead of using a state, which will cause re-rendering.
You can then use the this.user when the form submitted, for example.
3) Again, If you're not using user state in input text boxes for value, then you can also use React refs and get the value directly from the element when the form is submitted, for example.

You might try this in a parent component:
onTextBoxChange = (field, value) => {
this.setState({user:{
...this.state.user,
[field]: value
}
});
}
and then this in the child component:
onNameChange = (e) => {
this.props.onChange('name', e.target.value)
}
onAgeChange = (e) => {
this.props.onChange('age', e.target.value)
}

Related

How to setState from function parameter in React [duplicate]

This question already has answers here:
React this.setState is not a function
(16 answers)
Closed 3 years ago.
I am passing the name and value to handleChange function from child component.
Now I want to set the state to the value that matches the provided name.
But I do not know how to set it.
I tried this way(but it gives error - 'this.setState is not a function') :
class ParentComponent extends Component {
constructor(props) {
super(props);
this.myRef = React.createRef();
this.state = {
loanAmount: 348600.48,
numberOfYears: 70,
}
handleChange(name, value) {
this.setState({ name: value },() => {
this.financeCalcualte();
});
}
The code of the child component is:
onChange = (event) => {
const {name, rawValue} = event.target;
this.props.handleChange(name, rawValue)
}
What is the correct syntax to set it?
In order to use this in a callback function, as told in the comments you have to bind it in the constructor or use an arrow function.
Also, since your name is a variable, you can't update your state like:
this.setState({ name: value }
because this creates a name property in your state, does not update the state variable which has the name as your incoming variable. So, you should use a computed property.
handleChange = (name, value) =>
this.setState({ [name]: value }, () => this.financeCalcualte());
It seems like you are looking for computed property name
handleChange(name, value) {
this.setState({ [name]: value },() => {
this.financeCalcualte();
});
}
If you have this function in a Class based component then you can update your current function to an arrow function like below.
handleChange = (name, value) => {
this.setState({ name: value },() => {
this.financeCalcualte();
});
}
The thing is you are accessing this without a context being given.
Another way can be you bind this to the function. Below is the example to do it the other way inside your constructor.
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
// Other code ....
}
EDIT
Also as mentioned in other answer and comments you have to use computed property name, you can not just use a variable name directly and set it to another variable.
this.setState({[name]:value})

How to display submitted form data in same page in Reactjs?

I am new in reactjs. I want to submit form data in same page in reactjs. I am using array to store data but array stores data in one-dimensional and I want it in multi-dimentional form. How can I do that? I am using push() function and there are 5 input field in my form.
Here is my code:
var data = [{}];
export default class Form extends React.Component {
state = {
firstName: "",
lastName: "",
username: "",
email: "",
password: ""
};
change = e => {
this.props.onChange({ [e.target.name]: e.target.value });
this.setState({
[e.target.name]: e.target.value
});
};
onSubmit = e => {
e.preventDefault();
console.log(this.state);
data.push(this.state.firstName,this.state.lastName,this.state.username,this.state.email,this.state.password);
document.getElementById('hello').innerHTML = data;
};
render(){
//form input fields
}
}
Thank You.
Set all your form data values in a state object.
Once, submitted you can set all those values in your state and then you can view the updated state with your form data in the render method.
Something on the lines of
handleSubmit(data) {this.setState({formData: data})}
And then in your render you can view it as
render() { console.log(this.state.formData); return(...); }
Manipulate this variable as you want it now. Care needs to be taken that this state will be null/empty/undefined as per your declaration before the first submit.

Reactjs Select v2 - How to handle Ajax Typing?

I am using reactjs select 2 but I don't know how to make it work so that when a user types something in a ajax request is made and the results are sent back.
I see it has some async options but I don't get how it works and how I would get it to work with axios.
I come up with this but it is kinda laggy when a user types(probably because it is re-rendering it after each type) and when the user selects a choice the value disappears.
export default class TestComponent extends Component {
constructor(props) {
super(props);
this.state = {value: ""};
}
onInputChange(option) {
this.getOptionsAsync(option)
}
getOptionsAsync(newInput) {
var that = this;
console.log("ffd", newInput)
axios.get(`https://localhost:44343/api/States/GetStatesByText?text=${newInput}`)
.then(function (response) {
var formatedResults = response.data.map((x)=> {
return {value: x.id, label: x.name}
})
that.setState({
options: formatedResults,
value: newInput
})
})
.catch(function (error) {
});
}
render() {
console.log(this.state.value, "value")
return (
<div className="test">
<Select
onInputChange={this.onInputChange.bind(this)}
value={this.state.value}
options={this.state.options }
/>
</div>
);
}
}
You're going to be doing an api call every single time that you type a letter with the current way you're doing things. I would recommend just loading the states once at the beginning, perhaps in your ComponentDidMount() method.
If you pass the isSearchable prop to React-Select it will automatically work as a filter anyways.
Another thing I've had to do in this case which I believe will fix your change problem is to make sure it calls the handler on change not just on input change.
Pass this prop:
<Select
value={this.state.value}
options={this.state.options }
onChange={value => {
if (value) this.onInputChange(value)
else this.onInputChange('')
}
/>
Due to the way this is automatically bound to arrow functions, you won't have to bind to this if you change your onInputChange to the following:
onInputChange = (value) => {
this.getOptionsAsync(value)
}
Finally, you should be setting the state in the above function so the value is stored.
onInputChange = (value) => {
this.getOptionsAsync(value)
this.setState({value})
}

ReactJS change value of nested state

I have a form in which inputs have an initial value (which is different for each input). I set the value by saving the data in a state array, like so:
function createData(header, content) {
id += 1;
return {header, content, id};
}
class ExampleForm extends React.Component {
constructor(props) {
super(props);
this.state = {
data : [
createData( Header1, Content1),
createData( Header2, Content2),
createData( Header3, Content3),
]
}
Once the user startes typing something into the input field, I need to change the value of the state in in question in the corresponding array, however, I'm having trouble correctly targeting said state.
This is what I'm currently doing:
handleInputChange = (value, target) => {
const selectedArray = {...this.state.data[target]};
selArray.header = value;
this.setState(selArray);
};
}
(Note: value is the new value, target is the index)
However, it doesn't work because when I console.log() the new value, it still returns the old value.
I also read several other questions on here (with the help of with I wrote the code for what I'm doing right now in the function that changes the value), however, that did not work.
Other questions I read include React: Update nested state? , however, I could not figure out where they got getPersonsData() from, for instance. Does anyone know what I'm doing wrong in my current code? How do I fix it?
Update the state like this:
handleInputChange = (value, target) => {
const data = [...this.state.data];
data[target].header = value;
this.setState({ data });
};
To check the updated state value, use callback method, like this:
handleInputChange = (value, target) => {
const data = [...this.state.data];
data[target].header = value;
this.setState(
{ data },
() => console.log('updated state', this.state.data)
);
};
For more details about asyn behaviour of setState check this answer: Why calling setState method doesn't mutate the state immediately?

reactJs update state object without overwriting the object

I am having problems updating an object in this.state. Basically I have a form with multiple range sliders. Each time the slider is changed I want to update the this.state.dreadModel object, however I only seem to be able to overwrite it.
This is what I have tried so far:
this.setState( update ( this.state.dreadModel, { dreadModel: { [name]: e.target.value } } ), function () {
console.log(this.state);
});
The error I get with the above code is "Uncaught ReferenceError: update is not defined".
I feel like I am very close, but I cant quite get the syntax quite right.
Oh, here is the code I was using that would just overwrite the object each time a sliders value was changed.
this.setState({ dreadModel: {[name]: e.target.value }}, function () {
console.log(this.state);
});
What I usually do if I need to update a nested object, is something more like:
var dreadModel = {...this.state.dreadModel, [name]: e.target.value };
//or, if no ES6:
//var dreadModel = Object.assign({}, this.state.dreadModel);
//dreadModel[name] = e.target.value;
this.setState({ dreadModel: dreadModel }, function () {
console.log(this.state);
});

Resources