Add Name to Array using setState gives error - reactjs

Im trying to add an item to an array in my state. However, i get the following error:
Objects are not valid as a React child (found: object with keys...)
My github url to the codes, Please help.
class Tutorial2Screen extends Component {
constructor(props) {
super(props);
this.state = {
num: 0,
name: "",
arr: ["John", "Mary", "Steve"]
};
}
addNameToArr(newName) {
this.setState(prevState => ({
arr: prevState.arr.concat(newName)
}));
}
Input & Button codes:
<Input
placeholder="Name"
onChangeText={name => this.setState({ name })}
value={this.state.name}
/>
</Item>
<Button
block
style={{ margin: 10 }}
onPress={this.addNameToArr.bind(this)}
>

you have binded "addNameToArr" method with Button on press event, and in "addNameToArr" method, first argument you are expecting a "newName" (input field value) value to be passed in. But, as method is bind with an event call, so you are not getting text input value as argument.
Use:
addNameToArr() {
this.setState(prevState => ({
arr: prevState.arr.concat(prevState.name)
}));

You have to do it like this :
this.setState({
arr:this.state.arr.concat(this.state.name);
})
or you can use it like this by es6 spread syntax :
this.setState({
arr:[...this.state.arr,this.state.name];
})
changed newName to this.state.name because you are changing this.state.name with onchange handler not newName

thanks for all your help! your inputs have helped me find the solution to my question. I have altered my jsx code by adding in brackets and passing the argument directly to the arrow function and it worked! github contains the code that works.

Related

Set value of Reactstrap's Input to empty string

How do I set the value of a Reactstrap Input to be empty? I am using code like this.
handleChange = (event) => {
this.setState({message: event.target.value});
};
< Input onChange = {this.handleChange}/>
Also, what is the best practice for getting the value of an input: refs or onChange?
You gotta set a value property for your input which holds the value of your input, so your input looks like this:
<Input value={this.state.message} onChange={this.handleChange} />
and then when you want to clear its value, you just do this:
this.setState({message: ''})
and for your other question, the answer is that the Refs provide a way to access DOM nodes or React elements created in the render method, according to React documentation You can use Refs when:
Managing focus, text selection, or media playback.
Triggering imperative animations.
Integrating with third-party DOM libraries.
and you have to AVOID using refs for anything that can be done declaratively.
Then, here we just use onChange because we don't simply need Refs!
You need to assign state value to your input field.
public class myApp() extends React.Component {
constructor(props){
super(props);
this.state = {
message: ''
};
}
handleChange = (event) => {
this.setState({message: event.target.value});
};
render() {
return (
<Input value={this.state.message} onChange={this.handleChange} />
);
}
}

Is there any public react function that gets executed every time state is changed just like render function?

I have a child component. It should create an object from props and render it. This object should get added as a state.
Below is the current code.
Example:-
<popupComponent element={object} />
popupComponent.js
class popupComponent extends Component {constructor(props) {
super(props);
this.state = {
name: ""
}
}
updateName (event) {
this.setState({
name: event.currentTarget.value
})
}
publishElement () {
this.props.saveAndClose({
name: this.state.name
});
this.setState({
name: ""
})
}
render() {
return (
<div draggable="true" >
<h4>Name:</h4>
<input id="elementName" type="text" placeholder="Enter element name" value={element.name} onChange={this.updateName.bind(this)}/>
<button id="saveAndClose" onClick={this.publishElement.bind(this)}>Save & close</button>
</div>
);
}
}
export default popupComponent;
Question: Which function other than render gets executed whenever state is changed? In this scenario constructor runs only once and I cannot try that because the time constructor gets executed, state isnt available.
Resolved issue by conditionally not creating the component at all.
Actual issue, Somehow this component's constructor was getting called only once but I wanted it getting called whenever it gets visually shown.
Resolved issue by conditionally not including the component at all as below.
{this.state.show ? <PopupMarkupEditor
element = {selectedElement}
saveAndClose = {this.saveElement}
show = {this.state.show}
/> : null }

How to create a controlled Fabric UI TextField component?

I've been trying to code a controlled TextField component in the standard way just like in React docs:
handleChange(event) {
this.setState({
text: event.target.value
});
}
<TextField label='Enter Text' value={this.state.text} onChange={this.handleChange}/>
The code above is what I've been using, but it seems that it doesn't change the state of the react component, because in the same form if I change a controlled checkbox, it resets the textfield to be empty. If I use a standard html input element it works just as expected and doesn't clear the field.
What am I doing wrong here? Shouldn't TextField work the same way as a text type input?
From the docs, onChange is not a property. Use onChanged instead. Note that the return value is the textfield's value, not an event.
According to this example:
handleChange(value) {
this.setState({
text: value
});
}
I do not know what you want to do
but ... If what you need is to pass the input value to a text label, you can do it this way:
First you must declare an interface outside of your class
interface myState {
value1: string;
}
you must include your Interface in the class.
class TextFieldControlledExample extends React.Component<{}, myState> {...}
I suppose that for TypeScript themes you must publicly declare the interface of which you are using.
public state: myState = { value1: ''};
you must declare a function within the render to assign the value of the state
public render() {
const { value1 } = this.state;
in this way you assign the value of your inputs. but to update it you have to create a function and call it on the onChange
<TextField
label="Enter Text"
value={this.state.value1}
onChange={this._onChange}
styles={{ fieldGroup: { width: 300 } }}
/>
<Text variant='xxLarge' nowrap block>
{value1}
</Text>
to assign the input value to the state you have declared using setState. must do a function.
private _onChange = (ev: React.FormEvent<HTMLInputElement>, newValue?: string) => {
this.setState({ value1: newValue || '' });
};
You can see the example working here
https://codepen.io/jasp402/pen/EBWBgO

How to store an object in component's state?

I make an Ajax request that returns me an object like this :
Object { user1: "darkblue", user2: "darkred" }
How can I store this object in the component's state since none of the following works :
this.state = { usersColors: '' } // use for strings
this.state = { usersColors: [] } // used for arrays
Which syntax use for storing objects?
To initialise any variable as object, write it like this:
this.state = { usersColors: {} }
And use setState to update the state once you get the response, like this:
this.setState({usersColors: response})
Now you can access the response values by:
this.state.usersColors.user1 ----> "darkblue"
this.state.usersColors.user2 ----> "darkred"
Update:
Check this snippet:
let state = {
userColors: {
user1: 'red',
user2: 'blue'
}
}
let username = 'user1';
console.log('user1 value = ', state.userColors[username]);
You should never use this.state = ... anywhere except in a class constructor. Instead use this.setState({usersColors: {myObj: foo, etc: bar}}) One caveat: don't use this.setState in the render() method, you will just get an error.
How to map the different html elements who are going to be the part of the same array object to the object in the components state. Like if i have following two html elements who are part of a single object user
<div className="form-group">
<input
className="form-control"
type="text"
name="user[username]"
value={this.state.user.username}
onChange={this.onChange}
placeholder="Customer Name"
/>
</div>
<div className="form-group">
<input
className="form-control"
type="text"
name="user[mobilenumber]"
value={this.state.user.mobilenumber}
onChange={this.onChange}
placeholder="Customer mbole no."
/>
</div>
What should i give the name to these two elements such that they get mapped to the user object in the state present in the constructor
this.state = {
user: { username: "", mobilenumber: "" },
clothname: "",
description: "",
errors: {}
};
ANd with the following simple onChange function
onChange(event) {
this.setState({ [event.target.name]: event.target.value });
}

React: why binding value makes input readonly?

given this initial state:
this.state = {
person: { id: 1, name: "Liero" }
};
when I bind input like this: <input value={this.state.person.name} />
Then I makes the input non editable. I understand that it would make state and DOM element out of sync.
However, when I use defaultValue: <input defaultValue={this.state.person.name} />,
I loose posibility to change the person's name from code (e.g. when I want to reset the form).
When I manually sync the state and input value:
<input value={this.state.person.name}
onChange={(evt) => this.state.person.name = evt.target.value }/>
it does not work until I call setState, or force refresh?
Do I really need to force render of entire component each time the input value changes, when I want to have the posibility to control the person.name from code?
Instead of set this.state.person.name directly. call this.setState.
This will trigger another render cycle and then bind this.state.person.name to value:
<input value={this.state.person.name}
onChange={(evt) => {
this.state.person.name = env.target.value;
this.setState({person:this.state.person});
}}/>
Did you mean to setState() instead of mutate the state? like this:
class MyComponent extends Component {
state = { person: { id: 1, name: "Liero" } }
updateName = (e) => {
this.setState({
person: {...this.state.person, name: e.target.value}
})
}
render (){
return (
<input type="text" onChange={this.updateName} value={this.state.person.name} />
);
}
}

Resources