Edwin Barahona
Edwin Barahona

Reputation: 189

React v16: Uncaught TypeError: Cannot read property 'object' of undefined

I am getting this error and don't know what's wrong, my code is simple I'm just trying to push an array. Is so basic but yet can't figure it out.

I'm using Meteor 1.5.3 with React 16

import React, { Component, PropTypes } from 'react';

export default class ListMeds extends Component {
    render(){
        return(
            <li>{this.props.meds.text}</li>
        );
    }
}
ListMeds.propTypes = {
    meds: React.PropTypes.object.isRequired,
};

Upvotes: 2

Views: 14742

Answers (6)

krishna kurtakoti
krishna kurtakoti

Reputation: 128

I will show an example on how I changed the React.PropTypes.object to just PropTypes.object to resolve all the errors shown.The code source link is:

  1. https://github.com/jitsi/jitsi-meet/blob/move_logging_config/react/features/app/components/AbstractApp.js

  2. https://github.com/jitsi/jitsi-meet/blob/move_logging_config

import React, { Component } from 'react';

import {
    localParticipantJoined,
    localParticipantLeft
} from '../../base/participants';

import {
    appNavigate,
    appWillMount,
    appWillUnmount
} from '../actions';

/**
 * Default config.
 *
 * @type {Object}
 */
const DEFAULT_CONFIG = {
    configLocation: './config.js',
    hosts: {
        domain: 'meet.jit.si'
    }
};

/**
 * Base (abstract) class for main App component.
 *
 * @abstract
 */
export class AbstractApp extends Component {
    /**
     * AbstractApp component's property types.
     *
     * @static
     */
    static propTypes = {
        config: React.PropTypes.object,
        store: React.PropTypes.object,

        /**
         * The URL, if any, with which the app was launched.
         */
        url: React.PropTypes.string
    }

    /**
     * Init lib-jitsi-meet and create local participant when component is going
     * to be mounted.
     *
     * @inheritdoc
     */
    componentWillMount() {
        const dispatch = this.props.store.dispatch;

        dispatch(appWillMount(this));

        dispatch(localParticipantJoined());

        const config
            = typeof this.props.config === 'object'
                ? this.props.config
                : DEFAULT_CONFIG;

        this._openURL(this.props.url || `https://${config.hosts.domain}`);
    }

    /**
     * Dispose lib-jitsi-meet and remove local participant when component is
     * going to be unmounted.
     *
     * @inheritdoc
     */
    componentWillUnmount() {
        const dispatch = this.props.store.dispatch;

        dispatch(localParticipantLeft());

        dispatch(appWillUnmount(this));
    }

    /**
     * Create a ReactElement from the specified component, the specified props
     * and the props of this AbstractApp which are suitable for propagation to
     * the children of this Component.
     *
     * @param {Component} component - The component from which the ReactElement
     * is to be created.
     * @param {Object} props - The read-only React Component props with which
     * the ReactElement is to be initialized.
     * @returns {ReactElement}
     * @protected
     */
    _createElement(component, props) {
        /* eslint-disable no-unused-vars, lines-around-comment */
        const {
            // Don't propagate the config prop(erty) because the config is
            // stored inside the Redux state and, thus, is visible to the
            // children anyway.
            config,
            // Don't propagate the dispatch and store props because they usually
            // come from react-redux and programmers don't really expect them to
            // be inherited but rather explicitly connected.
            dispatch, // eslint-disable-line react/prop-types
            store,
            // The url property was introduced to be consumed entirely by
            // AbstractApp.
            url,
            // The remaining props, if any, are considered suitable for
            // propagation to the children of this Component.
            ...thisProps
        } = this.props;
        /* eslint-enable no-unused-vars, lines-around-comment */

        // eslint-disable-next-line object-property-newline
        return React.createElement(component, { ...thisProps, ...props });
    }

    /**
     * Navigates this AbstractApp to (i.e. opens) a specific URL.
     *
     * @param {string} url - The URL to which to navigate this AbstractApp (i.e.
     * the URL to open).
     * @protected
     * @returns {void}
     */
    _openURL(url) {
        this.props.store.dispatch(appNavigate(url));
    }
}

The changed code has the following after adding

yarn add prop-types
import PropTypes from 'prop-types';
export class AbstractApp extends Component {
    /**
     * AbstractApp component's property types.
     *
     * @static
     */
    static propTypes = {
        config: PropTypes.object,
        store: PropTypes.object,

        /**
         * The URL, if any, with which the app was launched.
         */
        url: PropTypes.string
    }
}

Upvotes: 0

Michael Flores
Michael Flores

Reputation: 726

The accepted answer correctly notes that prop-types is now its own package, I just wanted to add that if you're writing ES6 classes and already using ES6+ features, it might be more idiomatic to set PropTypes as a static variable on the class itself (note: this would apply in an environment using Babel with appropriate presets).

export default class ListMeds extends Component {
    static propTypes = {
         // propTypes
    }
    render() {
         // etc
    }
}

An Instagram engineer wrote a great post on React and ES6+. You can check out the proposal for class fields here and all the proposals here.

Upvotes: 1

Richard Rosario
Richard Rosario

Reputation: 81

I got the same issues.. and resolve it doing this:

import React, { Component, PropTypes } from 'react';

export default class ListMeds extends Component {
    render(){
        return(
            <li>{this.props.meds.text}</li>
        );
    }
}
ListMeds.propTypes = {
    meds: PropTypes.object.isRequired,
}

Upvotes: 0

Mikhail Shabrikov
Mikhail Shabrikov

Reputation: 8509

This error appears because of you use the 16th version of React.js. In this blog post (announce of React.js version 16) you can read:

The deprecations introduced in 15.x have been removed from the core package. React.createClass is now available as create-react-class, React.PropTypes as prop-types...

You should install prop-types module with (if you use npm):

npm install --save prop-types

or

yarn add prop-types

for yarn case. And rewrite your code this way:

import React, { Component } from 'react';
import PropTypes from 'prop-types';

export default class ListMeds extends Component {
    render(){
        return(
            <li>{this.props.meds.text}</li>
        );
    }
}
ListMeds.propTypes = {
    meds: PropTypes.object.isRequired,
};

Upvotes: 9

samcorcos
samcorcos

Reputation: 2488

If you're using React 15+, you need to import the prop-types package separately. Your code should read:

import React, { Component } from 'react';
import PropTypes from 'prop-types';

export default class ListMeds extends Component {
    render(){
        return(
            <li>{this.props.meds.text}</li>
        );
    }
}
ListMeds.propTypes = {
    meds: React.PropTypes.object.isRequired,
};

Note that the error says "object of undefined" which means React.PropTypes is undefined.

Upvotes: 1

Dane
Dane

Reputation: 9583

From React docs,

Note: React.PropTypes has moved into a different package since React v15.5. Please use the prop-types library instead. We provide a codemod script to automate the conversion.

See https://reactjs.org/docs/typechecking-with-proptypes.html
prop-types library: https://github.com/facebook/prop-types
Install the package and import it in your code.

Upvotes: 0

Related Questions