ReactJS unable to edit the textbox created through state variable - reactjs

I have the following code where the issue is the amount1 which the textbox is created through state is unable to edit. When i edit this textbox the value 10 is not changing from the textbox. The other normal textbox works as usual. Anyone knows the issue?
constructor(props) {
super(props);
this.state = {
amount1:"10",
amount2:"20",
input:"",
}
}
componentDidMount(){
var options = <input type="text" name="amount1" value={this.state.amount1}>
this.setState({'input':options})
}
render() {
return(
<div>
{this.state.input}
<input type="text" name="amount2" value={this.state.amount2}>
</div>
)
}

You are missing the close tag of input and since you are passing value from the state the input becomes read-only. So try defaultValue instead of value to make it editable.

Both your inputs don't change their value since they are bound to the values in the state,
this is your code
What you need to do is add an event handler to your input tag that changes the value saved in the state.
handleAmountInput = (event) => { this.setState({ amount: event.target.value }) }
render() {
return( this.handleAmountInput(event)} value={this.state.amount}> )
}
And you should close your input tag <input />

I think if you changed your render to the following, along w/ the onChange binding event, you should get the appropriate values in state.
onChange(event) {
this.setState({
[event.target.name]: event.target.value
});
}
render() {
return (
<div>
<input
type="text"
name="amount1"
value={this.state.amount1}
onChange={this.onChange.bind(this)}
/>
<input
type="text"
name="amount2"
value={this.state.amount2}
onChange={this.onChange.bind(this)}
/>
</div>
);
}
As mentioned previously, you are creating readOnly, uncontrolled elements. This is a good article on controlled (react recommended) vs uncontrolled:
https://goshakkk.name/controlled-vs-uncontrolled-inputs-react/

Related

onChange handler isn't updating state when I type in input

My onChange handler should be setting my state with whatever I type into the input, but when I log my state afterwards, it is not getting updated.
I am not sure what to try.
handleInputChange(e) {
this.setState({
insightsDTO: {
[e.target.id]: e.target.value
}
}, () => console.log(this.state, 'handle input change this.state'))
}
<div className="Form-group publish-insights-input">
<label class="Form-label">
URL <span className="asterisk">*</span>:
</label>
<input
type="text"
id="insightURL"
placeholder="URL"
class="Form-input"
onChange={this.handleInputChange}
value={this.state.insightsDTO ? this.state.insightsDTO["insightURL"] : ""}
/>
</div>;
When I check it out on the devtools, it's setting [e.target.id] to "insightURL" and e.target.value to whatever I'm typing in, but then afterwards when I log the state, I am not seeing that e.target.value. It's still just an empty string.
Did you bind your change handler in the constructor?
constructor(props) {
super(props);
this.state = {};
this.handleInputChange = this.handleInputChange.bind(this);
}
See a full example here:
Also see React docs for controlled components: https://reactjs.org/docs/forms.html#controlled-components
Unrelated, also make sure to use className (not class).

How access specific DOM in React js

I'm trying to get input tags' HTML inner values when submitting a form.
private handleSubmit = (event: any) => {
event.preventDefault();
console.log(event.currentTarget);
};
When the submit the form, it calls the function handleSubmit and it console logs the following.
Under the form tag, the first div has username value and the second div has password value. I would like to acess the two values. I think I should use DOM to do that, but can't be sure if I'm going for the right direction cuz I found some postings saying using DOM is not recommended.
Can anyone explain how I can acheive this?
Ideally you should update your state as the user enters information, and then access the data from the state. This would also allow you to run any validation on the data prior to it going into the state if you'd like.
import React, { Component } from 'react';
import './App.css';
class App extends Component {
constructor(props) {
super(props);
this.state = {
username: null,
password: null
}
this.submitForm = this.submitForm.bind(this);
this.updateState = this.updateState.bind(this);
}
updateState (e) {
this.setState({[e.target.name]: e.target.value})
}
submitForm (e) {
e.preventDefault();
console.log(this.state);
}
render() {
return (
<div className="App">
<form onSubmit={this.submitForm}>
<input type="text" name="username" placeholder="username" onChange={this.updateState} /><br />
<input type="password" name="password" placeholder="password" onChange={this.updateState} /><br />
<button type="submit">Submit</button>
</form>
</div>
);
}
}
export default App;
The above code does the following:
Stores default values for username and password. While this isn't required, it makes the code more readable
binds this to functions that need to access state
Uses an updateState() function that is called onChange of the inputs
updateState uses the name attribute of the input as the key for the state
You could customize the updateState() function to do some validation, before saving to state if you'd like.
Excessive Rendering
ReactJS is pretty smart to no re-render the REAL DOM if your render() method doesn't actually rely on the state values that were updated; however, if you'd like to prevent ReactJS from even creating the Virtual DOM and comparing, you could utilize the shouldComponentUpdate() lifecycle hook.
In the particular example above, since render doesn't rely on ANYTHING in state, you could simply add the following method:
shouldComponentUpdate(prevState, nextState) {
return false;
}
That will prevent the render method from EVER re-rendering, which is most likely not going to work in a normal component, thus you could do something like this instead, only re-rendering on values you care about.
shouldComponentUpdate(prevState, nextState) {
if (nextState.email !== prevState.email) {
return true
}
return false;
}
Demo
https://repl.it/#AnonymousSB/SO53689072
If you want to use the DOM, once you have the form element (event.currentTarget in your case), you can use the .elements property to access a list of child inputs and buttons.
Alternatively, you can use React refs to keep track of the underlying HTML element when it's rendered.
render() {
return ... <input ref={(e) => this._name = e; } ....> ... ;
}
handleSubmit(e) {
var name = this._name ? this._name.value : '';
....
}
This can achieve what you want to
class Login extends Component{
state={
username:"",
password:""
}
onChange = (event)=>{
event.preventDefault()
this.setState({
[event.target.name]: event.target.value})
}
onSubmit = (event)=>{
event.preventDefault()
// submit whatever is in state from here
console.log(this.state)
}
render(){
return(<div>
<form onSubmit={handleSubmit}>
<input type="text" name="username" onChange={this.onChange} /><br />
<input type="password" name="password" onChange={this.onChange} /><br />
<button type="submit">Submit</button>
</form>
</div>)
}
}

React form input won't let me change value

I have a component in a React class in my Laravel project which is a simple form with one input field. It houses a phone number which I have retrieved from the database and passed back through the reducer and into the component as a prop. Using this, I have passed it through to the module as a prop which then populates the field with the currently saved value:
<OutOfOfficeContactNumberForm
show={props.showOutOfOffice}
value={props.outOfOfficeNumber}
handleChange={console.log("changed")}
/>
I have a handleChange on here which is supposed to fire a console log, but it only ever displays on page load. Here is my form module class:
class OutOfOfficeContactNumberForm extends React.Component {
render() {
const { show, value, handleChange } = this.props;
if(!show) return null;
return (
<div>
<p>
Please supply an Out of Office contact number to continue.
</p>
<InputGroup layout="inline">
<Label layout="inline" required={true}>Out of Office Contact Number</Label>
<Input onChange={handleChange} value={value} layout="inline" id="out-of-office-number" name="out_of_office_contact_number" />
</InputGroup>
</div>
);
}
}
export default (CSSModules(OutOfOfficeContactNumberForm, style));
The form is embedded in my parent component, as follows:
return (
<SectionCategoriesSettingsForm
isSubmitting={this.state.isSubmitting}
page={this.props.page}
show={this.props.show}
categories={this.props.categories}
submitSectionCategoriesSettings={this._submit.bind(this, 'add')}
updateSelectedCategories={this._updateSelectedCategories.bind(this)}
selectedCategoryIds={this.state.selectedCategoryIds}
storedUserCategories={this.props.selectedCategories}
outOfOfficeNumber={this.state.outOfOfficeNumber}
onUpdateContactNumber={this._updateContactNumber.bind(this)}
/>
);
In my componentWillReceiveProps() function, I set the state as follows:
if (nextProps.selectedCategories && nextProps.selectedCategories.length > 0) {
this.setState({
outOfOfficeNumber: nextProps.outOfOfficeNumber,
selectedCategoryIds: nextProps.selectedCategories.map(c => c.id)
});
}
I'm pretty sure the reason it's not changing is because it's pre-loaded from the state which doesn't change - but if I cannot edit the field how can I get it to register a change?
EDIT: Just to clarify there are also checkboxes in this form for the user to change their preferences, and the data retrieved for them is set the same way but I am able to check and uncheck those no problem
Changes:
1- onChange expect a function and you are assigning a value that's why, put the console statement inside a function and pass that function toOutOfOfficeContactNumberForm component , like this:
handleChange={() => console.log("changed")}
2- You are using controlled component (using the value property), so you need to update the value inside onChange function otherwise it will not allow you to change means input values will not be not reflect in ui.
Check example:
class App extends React.Component {
state = {
input1: '',
input2: '',
}
onChange = (e) => this.setState({ input2: e.target.value })
render() {
return(
<div>
Without updating value inside onChange
<input value={this.state.input1} onChange={console.log('value')} />
<br />
Updating value in onChange
<input value={this.state.input2} onChange={this.onChange} />
</div>
)
}
}
ReactDOM.render(<App />, document.getElementById('app'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id='app' />
I think the best way is when you get data from database put it to state and pass the state to input and remember if you want to see input changes in typing, use a function to handle the change and that function should change state value.
class payloadcontainer extends Component {
constructor(props) {
super(props)
this.state = {
number:1
}
}
render() {
return (
<div>
<input value={this.state.number} onChange={(e)=>this.setState({number:e.target.value})}></input>
<button onClick={()=>this.props.buyCake(this.state.number)}><h3>buy {this.state.number} cake </h3></button>
</div>
)
}
}

Input field in not Editing..How to write onchange function for input field in reactjs

Im sending props value to the input field.When im trying to edit the
field it is not editing..How to write onchange handle function.Can anyone
explain briefly about controlled and uncontrolled inputs
handleUserInput = (e) => {
//what to do here in order to edit the input field
}
render() {
return(
<div>
<div className="info">
<label className="label">Store Name</label>
<input type="text"
ref="storename"
className="form-control"
value={this.props.storeName}
placeholder="Store Name"
onChange={this.handleUserInput}
disabled={this.state.disabled}
/>
</div>
</div>
);
}
Change this:
value={this.props.storeName}
to this (otherwise the value for input is always the same - the value received in props):
value={this.state.storeName}
and copy the props to the state in constructor(you should do that in constructor only if you are using props as an initial value):
constructor(props){
super(props)
this.state = {
storeName: props.storeName
}
}
and
handleUserInput=(e)=>{
this.setState({storeName: e.target.value});
}
Now we have made the input box a controlled element (with an initial value taking from the props though). If you are interested in controlled components more you can look in the docs, it isn't hard concept to grasp.

ReactJS: How-to set focus to input-element when it enters the DOM?

How to set focus to an input element when it enters the DOM?
Scenario
When a button is clicked the input element is displayed. How to set the focus to this element?
Code-Snippet
class Component extends React.Component{
constructor(props) {
super(props);
this.state = {
showInput: false
}
}
render() {
return (
<div>
<div onClick={() => {
this.setState({showInput: true});
ReactDOM.findDOMNode(this.refs.myInput).focus() // <- NOT WORKING
}}>
Show Input
</div>
{
(this.state.showInput) ? (
<input
type="text"
ref="myInput"
/>
) : ""
}
</div>
);
}
}
Calling ReactDOM.findDOMNode(this.refs.myInput).focus() after state change does not work. Also changing just the style or type property on state change does not work.
Assuming you only need one visible input on the page at a time to have autofocus Poh Zi How's suggestion of using the autofocus is probably the simplest.
<input type="text" autofocus/>
should do the trick, no JS needed!
In the componentDidMount and componentDidUpdate hooks do this:
ReactDOM.findDOMNode(this.refs.myInput).focus()
you should use ref
<input ref={(input) => { this.inputSearch = input; }} defaultValue="search ... " />
and use this code for focus
this.inputSearch.focus();
I had to define the variable as HTMLInputElement 1st...
private inputSearch: HTMLInputElement;
And then add this into the control:
ref={(input) => { this.inputSearch = input; }}
THEN I could get this to build/work:
this.inputSearch.focus();
From the docs:
"findDOMNode only works on mounted components (that is, components that have been placed in the DOM). If you try to call this on a component that has not been mounted yet (like calling findDOMNode() in render() on a component that has yet to be created) an exception will be thrown."
As mentioned by Piyush.kapoor, you need to place that incomponentDidMount and/or componentDidUpdate.

Resources