hulriche
hulriche

Reputation: 57

cannot read property of undefined - RENDER (input)

My program is a modification form.

I want to fill the tag with the value nom of my object: (nom: {id: "1", nom: "ENV"})

So I put in my this.state = {nom: ''}

I fill it with the function:

componentDidMount() {
    this.setState(() => ({ nom: this.props.store.environnements.find (p => p.id == this.props.environnement.match.params.id) }));
}

In my render () function, I entered in my value = {this.state.nom.nom} my page it correctly displays the name in the input.

But when I do a refresh, I get an error in the console:

"Uncaught TypeError: Cannot read property 'nom' of undefined at EditEnvironnementForm.render"

Could you help me solve this problem? Thank you!

import React from 'react';
import { connect } from 'react-redux';

export class EditEnvironnementForm extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            nom: '',
            error: ''
        };
        this.onNomChange = this.onNomChange.bind(this);
        this.onSubmit = this.onSubmit.bind(this);
    }

    onNomChange(e) {
        const nom = e.target.value;
        console.log(nom)
        this.setState(() => ({ nom: nom }));
    }

    onSubmit(e) {
        e.preventDefault();

        if (!this.state.nom) {
            this.setState(() => ({ error: 'Please set environnement!' }));
        } else {
            this.setState(() => ({ error: '' }));
            this.props.onSubmitEnvironnement(
                {
                    nom: this.state.nom,
                }
            );
        }
    }

    componentDidMount() {
        this.setState(() => ({ nom: this.props.store.environnements.find (p => p.id == this.props.environnement.match.params.id) }));
    }

    render() {
        return (
            <div>
                {console.log(this.state.nom)}
                {this.state.error && <p className='error'>{this.state.error}</p>}
                <form onSubmit={this.onSubmit} className='add-book-form'>

                    <input type="text" placeholder="nom" autoFocus
                        value={this.state.nom.nom}
                        onChange={this.onNomChange} />
                    <br />
                    <button>Add Environnement</button>
                </form>
            </div>
        );
    }
}

const mapStateToProps = (state) => {
    return {
        store: state
    };
};

export default connect(mapStateToProps)(EditEnvironnementForm);

Upvotes: 2

Views: 738

Answers (2)

Atiq Ur Rehman
Atiq Ur Rehman

Reputation: 109

you don,t need to this.setState in componentDidMount its not a good practice if you want to update the state according to the upcoming props then you simple do like that.

componentDidUpdate(prevsProp) {
    if (prevsProp.store !== this.props.store){
       this.setState({ nom: this.props.store.environnements.find (p => p.id == this.props.environnement.match.params.id) });
    }
}

In render method you need to do like this.

<input type="text" placeholder="nom" autoFocus
   value={this.state.nom || ''}
   onChange={this.onNomChange} 
/>

for more information please see the link https://reactjs.org/docs/react-component.html

Upvotes: 1

Vladimir Bogomolov
Vladimir Bogomolov

Reputation: 1794

Render lifecycle method executes before componentDidMount.

So in your render :

 <input type="text" placeholder="nom" autoFocus
   value={this.state.nom.nom}
   onChange={this.onNomChange} />
 <br />

this.state.nom is equal to a string (as you assigned it in the constructor) in the fist render. Then you set the this.state.nom to object through the componentDidMount but the first render has already failed and you get the error. To bypass this you have to check if this.state.nom is an object. Something like this:

<input type="text" placeholder="nom" autoFocus
   value={this.state.nom ? this.state.nom.nom : ''}
   onChange={this.onNomChange} 
/>

Upvotes: 1

Related Questions