Reputation:
I have a main class here that holds three states rendering a Form component:
class MainApp extends React.Component{
constructor(props){
super(props);
this.state = {
fName: '',
lName: '',
email: ''
}
render(){
return(
<div className="content">
<Form formState={this.state}/>
</div>
)
}
}
And then inside my Form component I have ff codes:
class Form extends React.Component{
constructor(props){
super(props);
}
render(){
return(
<form>
<input placeholder="First Name" value={this.props.formState.fName}
onChange={e => this.setState({ this.props.formState.fName: e.target.value })}
</form>
)
}
}
Upon running this codes, I got an error saying it cannot read the property 'fName' of null.
How do I properly pass one state to it's children component so it can modify the main one?
Upvotes: 0
Views: 508
Reputation: 158
I'm wondering why you want to pass a formState
to the form itself. The form should manage is own state. It is not a good practice to do 2 way binding like the Form mutate the MainApp's state
However, if for some reasons you need a copy of you formState
in your MainApp
component, then your Form
component should have an onSubmit
callback method.
class MainApp extends React.Component{
constructor(props){
super(props);
this.state = {
form: null
}
}
render() {
return(
<div className="content">
<Form onSubmit={(form) => {
this.setState({ form });
})}/>
</div>
)
}
}
class Form extends React.Component{
constructor(props){
super(props);
this.state = {
fName: '',
lName: '',
email: ''
}
}
render(){
return(
<form onSubmit={e => this.props.onSubmit(this.state) }>
<input placeholder="First Name" value={this.props.formState.fName}
onChange={e => this.setState({ this.props.formState.fName: e.target.value })}
</form>
)
}
}
Upvotes: 0
Reputation: 1057
class MainApp extends React.Component{
constructor(props){
super(props);
this.state = {
fName: '',
lName: '',
email: ''
}
this._handleChange = this._handleChange.bind(this);
}
//dynamically update the state value using name
_handleChange(e) {
const { name, value } = e.target;
this.setState({
[name]: value
});
}
render(){
return(
<div className="content">
//You can pass state and onchange function as params
<Form formState={this.state} _handleChange={this._handleChange}/>
</div>
)
}
}
class Form extends React.Component{
constructor(props){
super(props);
}
render(){
return(
<form>
<input placeholder="First Name"
defaultValue={this.props.formState.fName}
id="fName"
name="fName"
onChange={e => this.props._handleChange} />
</form>
)
}
}
Upvotes: 1
Reputation: 326
You can't edit parent's state directly from child component. You should define handlers that would change parent's state in parent component itself, and pass them to children via props.
Parent:
class MainApp extends React.Component{
constructor(props){
super(props);
this.state = {
fName: '',
lName: '',
email: ''
}
fNameOnChange = (value) => {
this.setState({fName:value})
}
render(){
return(
<div className="content">
<Form formState={this.state} fNameChange={this.fNameOnChange}/>
</div>
)
}
}
Child:
class Form extends React.Component{
constructor(props){
super(props);
}
render(){
return(
<form>
<input placeholder="First Name" value={this.props.formState.fName}
onChange={e => this.props.fNameChange(e.target.value))}
</form>
)
}
}
Upvotes: 1
Reputation: 1039
You should pass a function as a prop to update the state of parent component. It is advised not to change props directly.
In your parent class write a function like:
onChangeHandler (data) {
this.setState({fname: data})
}
And pass it to the child component and you can call this method as
this.props.onChangeHandler(event.target.data)
from child component.
Thanks
Upvotes: 0