I learn React and I faced some problems. I thought I understand controlled components, but well, it seems otherwise. Could you explain me, why after onChange event I receive props for rest Input components? If I want add label that depends on this.pops.name it gets messy (because of props I see in console.log). I would be grateful for explanation.
import React, { Component } from "react";
class Input extends Component {
handleChange = (e) => {
this.props.onInputChange(e);
};
chooseLabel = (props) => {
let { name } = props;
console.log(name);
if (name === "cost") {
return (
<label className="label" htmlFor={name}>
How much do you earn per hour?
</label>
);
} else if (name === "salary") {
return (
<label className="label" htmlFor={name}>
How much do you want to spend?
</label>
);
} else {
return null;
}
};
render() {
console.log("this.props.nevVal", this.props.newVal);
console.log("this.props.name", this.props.name);
return (
<div>
{this.chooseLabel(this.props)}
<input
className="Input"
value={this.props.newVal}
name={this.props.name}
placeholder={this.props.name}
onChange={this.handleChange}
/>
</div>
);
}
}
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
salary: "",
cost: "",
tip: ""
};
}
handleInputChange = (e) => {
console.log("E.target.name", e.target.name);
this.setState({ [e.target.name]: e.target.value });
};
render() {
return (
<div className="App">
<Input
name="salary"
newVal={this.state.salary}
onInputChange={this.handleInputChange}
/>
<Input
name="cost"
newVal={this.state.cost}
onInputChange={this.handleInputChange}
/>
<Input
name="tip"
newVal={this.state.tip}
onInputChange={this.handleInputChange}
/>
</div>
);
}
}
When one of the inputs is changed, you update the state of your App component. And when a state of a component is updated, it re-renders, and all its children too. So all the inputs are re-rendered (and their newVal
are logged to the console), even if you change the value of a single input.
I tried to illustrate it in the following snippet :
class Input extends React.Component {
handleChange = (e) => {
this.props.onInputChange(e);
};
chooseLabel = (props) => {
let { name } = props;
// console.log(name);
if (name === "cost") {
return (
<label className="label" htmlFor={name}>
How much do you earn per hour?
</label>
);
} else if (name === "salary") {
return (
<label className="label" htmlFor={name}>
How much do you want to spend?
</label>
);
} else {
return null;
}
};
render() {
console.log(`${this.props.name} input renderd`)
return (
<div>
{this.chooseLabel(this.props)}
<input
className="Input"
value={this.props.newVal}
name={this.props.name}
placeholder={this.props.name}
onChange={this.handleChange}
/>
</div>
);
}
}
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
salary: "",
cost: "",
tip: ""
};
}
handleInputChange = (e) => {
this.setState({ [e.target.name]: e.target.value });
};
render() {
console.log("App component and all its children rendered :")
return (
<div className="App">
<Input
name="salary"
newVal={this.state.salary}
onInputChange={this.handleInputChange}
/>
<Input
name="cost"
newVal={this.state.cost}
onInputChange={this.handleInputChange}
/>
<Input
name="tip"
newVal={this.state.tip}
onInputChange={this.handleInputChange}
/>
</div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
rootElement
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.0/umd/react-dom.production.min.js"></script>
<div id="root"></div>
Was that your question ?