Reputation:
I have an App here that has a child component and I am trying to set the state to whatever the user type something. I also want to track the changes the user is typing.
So far here's what I got:
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
firstName: "",
lastName: "",
userName: "",
email: "",
password: ""
};
this._handleChangeInput = this._handleChangeInput.bind(this);
}
componentDidMount() {}
_handleChangeInput(e) {
this.setState({
[e.target.name]: e.target.value
});
console.log("console log firstName >>>>>>", this.state.firstName);
}
render() {
return (
<div className="content">
<SignUp
formState={this.state}
_handleChangeInput={this._handleChangeInput}
/>
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById("app"));
And here is the child:
import React from "react";
class SignUp extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div>
<form>
<input
name="firstName"
id="firstName"
placeholder="First Name"
value={this.props.formState.firstName}
onChange={e => this.props._handleChangeInput}
/>
</form>
</div>
);
}
}
export default Form;
Whenever I am trying to type something in the textbox it won't allow me to do so and I don't see anything. What am I doing wrong here? And also how can I track what the user is typing on the textbox via console.log? I was trying to put some console.log inside the componentDidMount but it did not work.
Upvotes: 0
Views: 386
Reputation: 1590
You can use without e => this.props._handleChangeInput(e) too. You can make the function as below. Get the name and value of your input by destructuring as below.
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
firstName: "",
lastName: "",
userName: "",
email: "",
password: ""
};
this._handleChangeInput = this._handleChangeInput.bind(this);
}
_handleChangeInput(e) {
const { name, value } = e.target;
this.setState({
[name]: value
}, () => {
console.log("console log firstName >>>>>>", this.state.firstName);
});
}
render() {
return (
<div className="content">
<SignUp
formState={this.state}
_handleChangeInput={this._handleChangeInput}
/>
</div>
);
}
}
class SignUp extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div>
<form>
<input
name="firstName"
id="firstName"
placeholder="First Name"
value={this.props.formState.firstName}
onChange={this.props._handleChangeInput}
/>
</form>
</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"></div>
Upvotes: 0
Reputation: 6617
You can make use of componentWillReceiveProps() here
Pass your whole state
<div className="content">
<SignUp formState={this.state} _handleChangeInput={this._handleChangeInput} />
</div>
Now whenever the state in ParentComponent gets updated, It will get in componentWillReceiveProps()
in child component.
Child Component
class SignUp extends React.Component {
constructor(props) {
super(props);
}
componentWillReceiveProps(props){ // you will receive props here
this.setState(props.formState);
}
render() {
return (
<div>
<form>
<input
name="firstName"
id="firstName"
placeholder="First Name"
value={this.state.firstName}
onChange={e => this.props._handleChangeInput}
/>
</form>
</div>
);
}
}
Upvotes: 0
Reputation: 900
The problem here is that your are not controlling input value change on the SignUp component. Look at this sample:
<input type="textarea" value={this.state.relevantInfo} onChange={this.onRelevantInfo_Change}/>
onRelevantInfo_Change = (event) => {
this.setState({
relevantInfo: event.target.value
});
}
You must also bind the value from state object instead of doing from "props" as you are setting the updated value on the state
Besides, you are passing the full state from parent component to child component this way:
formState={this.state}
You should do it this way, spreading the attributes:
<SignUp {...props} />
Doing this way, it forces to decouple SignUp from its parent component (what you must do anyway), making it reusable.
Summarizing, refactor it to be independent, providing events, getters/setters... to the parent component to get the credentials entered in the sign up form.
Hope it helps.
Upvotes: 0
Reputation: 736
You are not passing event on your SignUp class e => this.props._handleChangeInput(e)
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
firstName: "",
lastName: "",
userName: "",
email: "",
password: ""
};
this._handleChangeInput = this._handleChangeInput.bind(this);
}
componentDidMount() {}
_handleChangeInput(e) {
this.setState({
[e.target.name]: e.target.value
}, () => {
console.log("console log firstName >>>>>>", this.state.firstName);
});
}
render() {
return (
<div className="content">
<SignUp
formState={this.state}
_handleChangeInput={this._handleChangeInput}
/>
</div>
);
}
}
class SignUp extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div>
<form>
<input
name="firstName"
id="firstName"
placeholder="First Name"
value={this.props.formState.firstName}
onChange={e => this.props._handleChangeInput(e)}
/>
</form>
</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"></div>
Upvotes: 1