1

I'm trying to develop a simple Dialog Component in react JS. I made something quite similiar before which works perfectly:

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { GridLoader as Loader } from 'halogen';
import httpCodes from 'http-status-codes';
import { Carousel } from 'react-responsive-carousel';

import 'react-responsive-carousel/lib/styles/carousel.css';

const NO_ELEMENT_SIZE = 0;
const TRANSITION_INTERVAL = 10000;

export default class MyCarousel extends Component {

    constructor(props) {
        super(props);

        this.state = {};
    }

    componentDidMount() {
        this.componentIsMounted = true;
        this.fetchMedia();
    }

    componentWillUnmount() {
        this.componentIsMounted = false;
    }

    fetchMedia() {
        fetch(this.props.url, {
            headers: { 'Content-Type': 'application/json' },
            method: 'GET'
        }).
        then((response) => {
            if (response.status >= httpCodes.BAD_REQUEST ||
                response.status === httpCodes.NO_CONTENT) {
                return Promise.reject(new Error(response.statusText));
            }

            return response.json();
        }).
        then((response) => {
            if (!this.componentIsMounted) {
                return;
            }

            const media = this.getMedia(response);
            this.setState({ media });
        });
    }

    getMedia(media) {
        const mediaList = [];
        let key = 0;
        media.forEach((mediaEntry) => {
            if (mediaEntry.type === 'image;imagem') {
                mediaList.push(<div key={key++}>
                    <img src={mediaEntry.url} />
                </div>);
            } else if (mediaEntry.type === 'video;vídeo') {
                mediaList.push(<div key={key++}>
                    <iframe src={mediaEntry.url} />
                </div>);
            }
        });

        return mediaList;
    }

    render() {
        if (!this.state.media) {
            return (
                <div className="hor-align vert-align">
                    <Loader color="#012935" className="loader"/>
                </div>
            );
        }

        if (this.state.media.length === NO_ELEMENT_SIZE) {
            return null;
        }

        return (
            <Carousel useKeyboardArrows autoPlay infiniteLoop
                      showArrows showThumbs={ false } showStatus={ false }
                      interval={TRANSITION_INTERVAL}>
                {this.state.media}
            </Carousel>
        );
    }
}

MyCarousel.propTypes = { url: PropTypes.string.isRequired };

So, I did exactly the same for my Dialog component but I keep getting the error: this.setState is not a function. Why does one works and the other one doesnt?

import React, { Component } from 'react';
import Dialog from 'material-ui/Dialog';
import FlatButton from 'material-ui/FlatButton';
import TextField from 'material-ui/TextField';
import RaisedButton from 'material-ui/RaisedButton';
import PropTypes from 'prop-types';

export default class MyDialog extends Component {

    constructor(props) {
        super(props);

        this.state = { open: false };
    }

    handleOpen() {
        this.setState({ open: true });
    }

    handleClose() {
        this.setState({ open: false });
    }

    render() {
        const actions = [
            <FlatButton
                label="Cancel"
                primary
                onTouchTap={this.handleClose}
            />,
            <FlatButton
                label="Submit"
                primary
                keyboardFocused
                onTouchTap={this.handleClose}
            />
        ];

        return (
            <div>
                <RaisedButton label="Dialog" onTouchTap={this.handleOpen} />
                <Dialog
                    title="Dialog With Actions"
                    actions={actions}
                    modal={false}
                    open={this.state.open}
                    onRequestClose={this.handleClose}
                >
                    <TextField hintText="Hint Text"
                               />
                </Dialog>
            </div>
        );
    }
}

MyDialog.propTypes = {
    open: PropTypes.bool.isRequired,
    poiId: PropTypes.string,
    url: PropTypes.string.isRequired,
    user: PropTypes.any
};

And finally, the component where I call my MyDialog component.

Any idea what's wrong?

Kind regards

vftw
  • 1,547
  • 3
  • 22
  • 51
  • 2
    I'm not a react expert, but you could try binding ```this``` to your method in the onTouchTap attribute: ```this.handleClose.bind(this)``` – j3py Apr 30 '17 at 19:41
  • 1
    yes @j3py is right, you need to `bind` the `handleOpen` and `handleClose` function either in `constructor` or use `arrow function` like this: `handleOpen = () => {` it will work. – Mayank Shukla Apr 30 '17 at 19:44
  • If I change to arrow function I get `Unexpected token =`. Only on the first function (handleOpen). That's kinda odd, right? – vftw Apr 30 '17 at 20:10
  • Use onTouchTap={()=>this.setState({ open: false })} directly. This creates a function on each re-render so as already suggested, binding the method in the constructor is ever so slightly more performant. this.handleClose = this.handleClose.bind(this) – Per Svensson May 01 '17 at 00:32

0 Answers0