Reputation: 1455
I have two files: App.js that's handling state and Counter.js. Everything gets displayed, accept onChange doesn't update the values in the input. What am I doing wrong in the Counter? Should I handle it differently than using props?
import React, { Component } from 'react';
import Counter from './components/Counter';
import './App.css';
class App extends Component {
state = {
cost: 0,
houseCost: 0,
downPayment: 0,
termOfLoan: 0,
annualInterestRate: 0
}
handleChange(e) {
this.setState({houseCost: e.target.houseCost});
}
handleCostChange = () => {
this.setState(
prevState => ({
cost: prevState.cost += 1
})
);
}
render() {
return (
<div className="App">
<Counter
cost={this.state.cost}
houseCost={this.state.houseCost}
downPayment={this.state.downPayment}
termOfLoan={this.state.termOfLoan}
annualInterestRate={this.state.annualInterestRate}
changeCost={this.handleCostChange}
handleChange={this.handleChange}
/>
</div>
);
}
}
export default App;
Counter.js
import React from 'react';
const Counter = (props) => {
return (
<div className="counter">
<input type="text" value={props.houseCost} placeholder="House Cost" onChange={() => props.handleChange}></input>
<input type="text" value={props.downPayment} placeholder="Down Payment" onChange={() => props.handleChange}></input>
<input type="text" value={props.termOfLoan} placeholder="Mortgage Period (years)" onChange={() => props.handleChange}></input>
<input type="text" value={props.annualInterestRate} placeholder="Interest Rate" onChange={() => props.handleChange}></input>
<button className="counter-action" onClick={props.changeCost}>Calculate</button>
<span className="counter-score">{ props.cost }</span>
</div>
);
}
export default Counter;s
Upvotes: 0
Views: 7658
Reputation: 96
change handleChange to an arrow function. It is not bound to the class so an arrow function will remove the context or you can bind the function in the constructor.
handleChange = (e, key) => {
this.setState({[key]: e.target.value});
}
this gives you a dynamic key so that you can use this handeChange function for all of your inputs and not have to write a new one.
also on your event in count.js isn't passing back the event.
onChange={(e) => props.handleChange(e, 'houseCost')}
Upvotes: 4
Reputation: 116
the issue is in your onChange handler. When you call this method you change the state only of one value "houseCost" and finally, the expected "e.target.value" is not correct. Try something like this:
this.setState({ [e.target.name]: e.target.value });
And for each input like:
<input type="text" name="houseCost" value={props.houseCost} placeholder="House Cost" onChange={() => props.handleChange} />
So, the input attribute "name" allows you to specify "event target name" and use them to change specific state value by "event target value" by one handler
Upvotes: 4
Reputation: 14927
You've got a couple problems, both in the handleChange function, and the way it's called from counter. See the example below:
class App extends React.Component {
state = {
cost: 0,
houseCost: 0,
downPayment: 0,
termOfLoan: 0,
annualInterestRate: 0
}
handleChange = (e, key) => {
this.setState({[key]: e.target.value});
}
handleCostChange = () => {
this.setState(
prevState => ({
cost: prevState.cost += 1
})
);
}
render() {
return (
<div className="App">
<Counter
cost={this.state.cost}
houseCost={this.state.houseCost}
downPayment={this.state.downPayment}
termOfLoan={this.state.termOfLoan}
annualInterestRate={this.state.annualInterestRate}
changeCost={this.handleCostChange}
handleChange={this.handleChange}
/>
</div>
);
}
}
const Counter = (props) => (
<div className="counter">
<input
type="text"
value={props.houseCost}
placeholder="House Cost"
onChange={e => props.handleChange(e, 'houseCost')}
/>
<input
type="text"
value={props.downPayment}
placeholder="Down Payment"
onChange={e => props.handleChange(e, 'downPayment')}
/>
<input
type="text"
value={props.termOfLoan}
placeholder="Mortgage Period (years)"
onChange={e => props.handleChange(e, 'termOfLoan')}
/>
<input
type="text"
value={props.annualInterestRate}
placeholder="Interest Rate"
onChange={e => props.handleChange(e, 'annualInterestRate')}
/>
<button className="counter-action" onClick={props.changeCost}>Calculate</button>
<span className="counter-score">{ props.cost }</span>
</div>
);
ReactDOM.render(
<App />,
document.getElementById("react")
);
<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="react"></div>
Upvotes: 3