1

In the code provided below I am able to see this.mBaseService is defined above the first debugger but not below the second debugger.

Is anyone able to explain why this is the case? One theory I had is that React or Next.js may be internally clearing properties.

    import Link from 'next/link';
    import React, { Component, Fragment } from 'react';

    import ReactDropzone from 'react-dropzone';
    import { Container, Row, Col, Button, Jumbotron, ListGroup, ListGroupItem } from 'reactstrap';

    import DefaultHomeView from '../components/default-home-view';
    import Page from '../components/page';
    import EteeReport from '../components/etee-report';
    import Layout from '../components/layout';
    import { ServiceBaseService } from '../services/service-base/service-base.service';

    export default class extends Page {
        mBaseService = new ServiceBaseService();

        constructor(props) {
            super(props);

            this.state = {
                files: [],
            };

            console.log('it exists!', this.mBaseService);
            debugger;
            //this.mBaseService = new ServiceBaseService();
        }

        fHandleOnDrop = async files => {
            debugger;
            const oResponse = await this.mBaseService.fpPost('/reports', {
                oDataToPost: JSON.stringify(files),
            });

            // TODO: if valid csv then parse and chart the data
            this.setState({
                files: this.state.files.concat(files),
            });
        };

        fClearFiles = () => {
            this.setState({
                files: [],
            });
        };

        render() {
            return (
                <Layout {...this.props} navmenu={false} container={false}>
                    {!this.state.files.length && (
                        <DefaultHomeView {...this.props} fHandleOnDrop={this.fHandleOnDrop} files={this.state.files} />
                    )}
                    {this.state.files.length && <EteeReport {...this.props} {...this.state} fClearFiles={this.fClearFiles} />}
                </Layout>
            );
        }
    }
John Vandivier
  • 2,158
  • 1
  • 17
  • 23
  • 1
    If you `console.log(this.mBaseService)` in either the constructor or in `fHandleOnDrop` I think you will see that's it's accessible in both places. I'm not sure why you can't see it in the debugger though. – Tholle Aug 12 '18 at 02:00
  • That's true. Weird. If I call `console.log(this.mBaseService)` in `fHandleOnDrop` I see the expected result, even though if I'm in dev tools and I log `this.mBaseService` to console it comes as undefined. I'd still like to know *why*, but I'll close if recommended. – John Vandivier Aug 12 '18 at 02:17
  • @Tholle this answers a second question I had also. You see how this `class extends Page`? Well, `Page` also has `mBaseService = new ServiceBaseService();`, but it wasn't showing for me when debugging. Now if I comment that property on the child class and I `console.log` I can see it, even though if I `debugger` and interrogate on the console it's undefined. – John Vandivier Aug 12 '18 at 02:23

1 Answers1

1

This problem is likely specific to how the code is transpiled with Babel. As explained in this related answer, class fields (arrow methods) are transpiled to constructor code and this is replaced with _this, _this2, etc. temporary variables where needed to mimic the behaviour of lexical this in arrows.

A property may not be available on this in debugger but on temporary _this? variable which is considered proper context in original code.

In this specific case this is caused by the fact that fHandleOnDrop is passed as callback:

<DefaultHomeView {...this.props} fHandleOnDrop={this.fHandleOnDrop} files={this.state.files} />

This means this.props.fHandleOnDrop() has been dereferenced and is being called with wrong this , while the function uses _this? variable internally to refer to proper context:

    fHandleOnDrop = async files => {
        console.log(this.mBaseService) // should be ok
        eval('console.log(this.mBaseService)') // should fail

This likely wouldn't be the case if Babel was configured to not transpile arrows to ES5 target by not using es2015 preset.

Regardless of these concerns, there is always a chance that this behaviour is specific to particular development tools.

Estus Flask
  • 206,104
  • 70
  • 425
  • 565