React Input Element: Value vs Default Value

I am new to React and REDUX, I just developed a simple responsive application, and now I encounter a problem when I render an input element inside my component, if I set the element to β€œvalue”, it becomes read-only, but if I install value on defaultValue, it will never be updated again when I re-update my state.

Here is my code:

import React from "react"; export default class EditForm extends React.Component { editTransaction(event) { var transaction = this.props.transaction; event.preventDefault(); var NewTransaction = { transactions_data: { amount: this.refs.amount.value } } this.props.editTransaction(NewTransaction, transaction.id); } closeForm() { this.props.closeForm(); } render() { var {amount}=this.props.transaction; return ( <div> <br/> <h4>Edit Transaction</h4> <div className="btn btn-danger pull-right" onClick={this.closeForm.bind(this)}>close</div> <div className="clearfix"></div> <form onSubmit={this.editTransaction.bind(this)}> <div> <label for="amount">Amount</label> <input value={amount} onChange={(value) => this.onChange(value)} className="form-control" id="amount" name="amount" type="number" ref="amount"/> </div> <br/> <br/> <input className="btn btn-info" type="submit" value="submit"/> </form> </div> ); } } 

and then I found out if I can make a mistake from this by adding onChange={(value) => this.onChange(value)} on my input element, it works correctly (it updates when updating the props or status, and I can reuse enter value), but I think this is not the right solution, because it causes errors on my browser console, This is because the this.onChange function does not exist.

please kindly help me solve this problem and thanks in advance

Hello,

Vidy

+5
source share
3 answers

The reason you enter doesn't work, because you need to define the onChange function, which actually sets the state with the updated value. Perhaps you can do it inline, as this is only for instruction, for example

 <input type="text" value={this.state.inputVal} onChange={(e) => {this.setState({inputVal: e.target.value})}} /> 

However, I would recommend that you use the onChange method, since you can handle multiple inputs with it, and it looks cleaner.

 class EditForm extends React.Component { constructor() { super(); this.state = { } } onChange(e) { this.setState({[e.target.name]: e.target.value}) } editTransaction(event) { var transaction = this.props.transaction; event.preventDefault(); var NewTransaction = { transactions_data: { amount: this.refs.amount.value } } this.props.editTransaction(NewTransaction, transaction.id); } closeForm() { this.props.closeForm(); } render() { return ( <div> <br/> <h4>Edit Transaction</h4> <div className="btn btn-danger pull-right" onClick={this.closeForm.bind(this)}>close</div> <div className="clearfix"></div> <form onSubmit={this.editTransaction.bind(this)}> <div> <label for="amount">Amount</label> <input value={this.state.amount} onChange={(value) => this.onChange(value)} className="form-control" id="amount" name="amount" type="number" ref="amount"/> <input value={this.state.amount1} onChange={(value) => this.onChange(value)} className="form-control" id="amount1" name="amount1" type="number" ref="amount"/> </div> <br/> <br/> <input className="btn btn-info" type="submit" value="submit"/> </form> </div> ); } } ReactDOM.render(<EditForm/>, document.getElementById('app')); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.2/react.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.2/react-dom.min.js"></script> <div id="app"></div> 
+7
source

You need to define the onChange method if you use a shortcut, which can be an action that updates the state of your component through a reducer. Below is a simpler method using simple state with es6. In addition, you get the value from the input field through ref , which is not encouraged by Facebook. This should also lead to an error, because you are trying to control and uncontrol a component.

Here is a link to the form documentation for further reading.

 class Foo extends React.Component { constructor(props) { super(props); this.state = ({ inputVal: '', }); } onChange = (e) => { this.setState({ [e.target.name]: e.target.value }); } handleSubmit = (event) => { event.preventDefault(); console.log(this.state.inputVal); } render() { return ( <div> <input type="text" value={this.state.inputVal} onChange={this.onChange} /> </div> ); } } 
+2
source

I did this and found a very simple solution:

 class App extends Component { constructor(props) { super(props) this.enterText = this.enterText.bind(this) this.state = { userNameText: 'user name', pswdText: 'pswd', textEntry: false } } async enterText() { if (!this.state.textEntry) { await this.clearText() this.setState({textEntry: true}) } } clearText() { this.setState({ userNameText: '', pswdText: '' }) } render() { return ( <div className="App"> <div className="App-header"> <h1 className="App-title"> Welcome </h1> </div> <div className="login-fields"> <LoginFields userNameText={this.state.userNameText} pswdText={this.state.pswdText} onFocus={this.enterText} /> </div> </div> ) } } 

So, with the initial render (), the state of the fields is what is hardcoded in the constructor. When the user clicks either the name or the pswd field (they can be easily separated), both are cleared with clearText (), and then both values ​​are null with allowText (). Once set to null, user input text is accepted.

Verify that the LoginFields component has this input value:

onFocus={this.props.onFocus}

0
source

Source: https://habr.com/ru/post/1265482/


All Articles