Why is my input not updating? - React - reactjs

I can't figure out why my input is not updating. Here is my code:
state = {
org: {
orgName: ''
}
};
updateInput = field => event => {
this.setState({
[field]: event.target.value
})
}
render() {
let { org } = this.state
return (
<input
value={org.orgName}
onChange={this.updateInput('orgName')}
/>
)
}
I type data into the input. It calls updateInput and sets the state. When render is called, the org.orgNameis '' again. This should be working.
I have even added a log in the setState callback:
this.setState({
[field]: event.target.value
}, () => console.log(this.state.org))
and it logs out the org info that has been entered into the input
What am I missing? How do I make this work?

You have a nested object in your state - you are updating this.state.orgName instead of this.state.org.orgName
updateInput = field => event => {
this.setState({
[field]: event.target.value
})
}
needs to be
updateInput = field => event => {
this.setState({
org: {
...this.state.org,
[field]: event.target.value
}
})
}
Would recommend you avoid nesting objects in state though going forward. Will prove difficult to optimize later on.

Related

React.JS TypeError: Cannot read property 'number' of undefined - (inside setState)

Hello everyone,
In my ReactJS website I get this error - `TypeError: Cannot read property 'number' of undefined`
`HTMLInputElement.anonymous ` why ?
I did console.log(this.state.number) and number has a value in it.
class App extends Component {
constructor(props) {
super(props);
this.state = {
mobileNum: '',
number: '',
};
}
somefunction=()=>{ // Is called with onKeyDown - I checked it does.
this.setState({ number: document.getElementById('mySubmit').value });
enterPressed = () => {
const submit = document.getElementById('mySubmit');
submit.addEventListener('keyup', function (event) {
if (event.key === 'Enter') {
this.setState({ mobileNum: this.state.number }); // Here is the error line !
}
});
};
If I use setState with if condition in another function it will do error - setState is not a function
this.setState({ mobileNum: this.state.number }) is working also in a different fuction I made, but in enterPressed() isn't.
Thanks for the helpers :)
It should be a fat arrow function
enterPressed = () => {
const submit = document.getElementById('mySubmit');
submit.addEventListener('keyup', (event) => {
if (event.key === 'Enter') {
this.setState({
mobileNum: this.state.number
});
}
});
};
You never call someFunction() which is supposed to assign a number value to this.state.number. When you try to assign this.state.number to mobileNum, the value is still undefined.
Instead of using HTML selectors in this function, you can add two-way binding:
enterPressed = (e) => {
e.preventDefault();
let password = e.target.value();
this.setState({ ...this.state, mobileNum: password});
};

React app render function executes before state is set?

I am building a chatting app in React, but it crashes right after sending a message. Here is part of the code
state ={
conversationData: null,
message: ''
};
componentDidMount() {
this.setState({conversationData: this.props.conversationData});
};
onSendClicked = () => {
con.addMessage(this.state.conversationData.id, data).then(() => {
this.setState({message: ''}, () => {
this.setState({conversationData: this.state.conversationData.message.push(data)});
});
});
};
and in my render function, I have this
<List>
{this.state.conversationData.message !== null && this.state.conversationData.message !== undefined ?
this.state.conversationData.message.map((mes, index)
........
: <div/>....
The problem is in that loop, it works fine when I load it, but once I press send message and set the state on conversationData, it either returns an empty div and never updates or crashes with .map() is undefined if I eliminate that div. What am I doing wrong?
Based on your current code this is how I would set it up:
state ={
conversationData: this.props.conversationData, // no need to set it as null then update on mount
message: ''
};
onSendClicked = () => {
con.addMessage(this.state.conversationData.id, data).then(() => {
this.setState(({ conversationData }) => ({
message: '',
conversationData: {
...conversationData,
message: [ ...conversationData.message, data ] // where is this data coming from?
} // update conversationData with message
});
};
assuming that 'con' is defined and has a method named 'addMessage' that isn't returning an error
i'm also assuming that you have a type-o and data is being passed in from onSendClicked(data)
then i would do this. take special notice to the spread operator
[...this.state.conversationData.message, data.id]
as opposed to mutating state with .push()
as well as initializing conversationData.message state with an [] to avoid iteration errors on null (check for conversationData.message.length instead of conversationData.message !== null)
state ={
conversationData: {message:[]},
message: ''
};
componentDidMount() {
this.setState({conversationData: this.props.conversationData});
};
onSendClicked = (data) => {
con.addMessage(this.state.conversationData.id, data)
.then(() => {
this.setState({
message: '',
conversationData: [...this.state.conversationData.message, data]
})
});
};
in render:
<List>
{
this.state.conversationData.message.length && this.state.conversationData.message.map((mes, index)=>{
//dosomething with mes and index
})
}
</List>

react hook can not clear input value

my component look like this
const onkeychange = async (e) => {
setState({ ...state, textValue: e.target.value })
if (delay !== false) {
clearTimeout(delay)
}
let string = e.target.value
if (string.trim() == '') {
setState({ ...state, issearching: false })
}
}
<input
type="text"
autoComplete="off"
name="search"
placeholder="Search for a Product, Brand or Category"
value={state.textValue}
className="search"
onChange={onkeychange}
/>
problem is, When after I type something in the input. Then try to delete everything, I can't I can delete all but one last character. For exmaple: I type hello in the input. trying to delete it with backspace, I can remove ello but not the h
You're checking if string === '' and case true you're setting the state using the old state which includes string's value just before deleting the last char, this is why you can't delete the last one. You should remove the condition
const onkeychange = async (e) => {
setState({ ...state, textValue: e.target.value })
if (delay !== false)
clearTimeout(delay)
}
Use functional form of setState to get the latest state when updating it. Also I'd recommend to consider using reducer hook here.
const onkeychange = async e => {
const value = e.target ? e.target.value : "";
setState(currentState => ({ ...currentState, textValue: value }));
if (delay !== false) {
clearTimeout(delay)
}
if (value.trim() === "") {
setState(currentState => ({ ...currentState, issearching: false }));
}
};
The setState is async, you can use a callback in the setState to get the correct preState to solve this problem.
const string = e.target.value;
setState((prevState) => {
return { ...prevState, textValue: string }
})
if (delay !== false) {
clearTimeout(delay)
}
if (string.trim() === '') {
setState((prevState) => {
return ({ ...prevState, isSearching: false })
})
}
or a more simple way is to only run setState once.
const string = e.target.value
if (delay !== false) {
clearTimeout(delay);
}
const isSearching = string.trim() !== "";
setState({ ...state, textValue: string, isSearching});
view demo on code sandbox

The cursor backspace doesn’t remove last char of number format in react

I am new to react.
For e.g, input value entered 1,2,3,4 and after the event onChange it takes only numbers, then I can
remove 4,3,2 with backspace but not 1. And in HTML DOM also, the 1 cannot be removed.
class House extends Component {
state = {
room: null,
};
componentDidMount() {
if (this.props.house.rent) {
this.setState({ rent: this.props.house.rent });
}
}
onChange = (field, value, mutate) => {
if (field === "houseroom") {
value = parseInt(value.replace(/[#,]/g, ""));
}
mutate({
variables: {
},
});
this.setState({
[field]: value,
});
};
render(){
const {house} = this.props;
<SomeInput
type="text"
value={
(house.room&&
`$${house.room.toLocaleString("en")}`) ||
""
}
onChange={e => {
e.target.placeholder = "Room";
this.onChange("houseroom", e.target.value, mutate);
}}
}
/>
}
It look like a lot of a problem during the update of the state probably due to overrendering elsewhere in the component try to use prevState instead do ensure that state updating can not conflict.
this.setState(prevState => {
[field]:value;
});
Keep me in touch with the result.
Hope this helps someone !
Need to mention "this.state.room" in the input Value and check the prev state using the componentDidUpdate then "this.setState" here and also finally "this.setState" during the event change. Thanks all

Simple setState on object using hooks

const [state, setState] = useState({ city: '', country: '' });
const handleCityChange = event => {
setState(prevState => {
console.log(prevState);
return { ...prevState, city: event.target.value };
});
};
//...
<input
type="text"
placeholder="city"
value={state.city}
onChange={handleCityChange}
/>
I'm trying to destructuring prevState, which is an object, and update only the city property. On first keystroke, it's working fine without error, but as soon as I'm typing second letter, i will hit error
Uncaught TypeError: Cannot read property 'value' of null
May I know which part is the null coming from? And from chrome console I see below warning not sure if it's related
Warning: This synthetic event is reused for performance reasons. If you're seeing this, you're accessing the property target on a released/nullified synthetic event. This is set to null. If you must keep the original synthetic event around, use event.persist(). See https:...//react-event-pooling for more information.
UPDATES:
If we're not using setState functionally, then it's working fine?
const handleCityChange = event => {
setState({ ...state, city: event.target.value });
};
An event has to be handled synchronously in React. You can extract the value from the target before you call setState:
const handleCityChange = event => {
const { value } = event.target;
setState(prevState => {
return { ...prevState, city: value };
});
};
Another way of going about it is to persist the event, and it can be used asynchronously.
const handleCityChange = event => {
event.persist();
setState(prevState => {
return { ...prevState, city: event.target.value };
});
};

Resources