Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

When using react-hot-loader with pure Preact this.props and this.state are not passed as render() args #1013

Closed
kroko opened this issue Jun 8, 2018 · 3 comments
Assignees
Labels

Comments

@kroko
Copy link

kroko commented Jun 8, 2018

Description

I thought to give Preact a try. The pure approach.
Currently it seems everything is working smoothly, EXCEPT that render(props, state) behaviour described in Preact docs

Components also have a render() method, but unlike React this method is passed (props, state) as arguments. This provides an ergonomic means to destructure props and state into local variables to be referenced from JSX.

gets broken, meaning - no props and state is passed in render.

Expected behavior

  render (props, state) {
    const {counter} = state;
    return (
      <div>
        <h3>{`ComponentPreact`}</h3>
        <p>{`Current count is ${counter}`}</p>
      </div>
    );
  }

should render counter.

Actual behavior

state in render(props, state) {} is undefined.

ComponentPreact.js?636f:113 Uncaught (in promise) TypeError: Cannot destructure property `counter` of 'undefined' or 'null'.
    at ProxyComponent.render (ComponentPreact.js?636f:108)
    at ProxyComponent.hotComponentRender (react-hot-loader.development.js?c2cb:622)
    at ProxyComponent.proxiedRender (react-hot-loader.development.js?c2cb:630)
    at renderComponent (preact.esm.js?30bf:728)
    at setComponentProps (preact.esm.js?30bf:676)
    at buildComponentFromVNode (preact.esm.js?30bf:842)
    at idiff (preact.esm.js?30bf:397)
    at innerDiffNode (preact.esm.js?30bf:516)
    at idiff (preact.esm.js?30bf:439)
    at diff (preact.esm.js?30bf:348)

Thus props and state are not passed into render function. Forgetting about method args and manually destructuring of course works =>

  render () {
    const {counter} = this.state;
    return (
      <div>
        <h3>{`ComponentPreact`}</h3>
        <p>{`Current count is ${counter}`}</p>
      </div>
    );
  }

Actually I don't mind 😆 as I'm used destructuring only what is needed out of state and props in render function anyway and const {a, b, c} = this.state; comes naturally.
Anyways, it seems that RHL breaks this Preact feature. Either it needs to be documented ar maybe it can be fixed. I have no idea what happens in preact-compat.

Environment

React Hot Loader version: 4.3.0
preact: 8.2.9

Run these commands in the project folder and fill in their results:

  1. node -v: v8.11.2
  2. npm -v: 6.1.0

Then, specify:

  1. Operating system: macOS 10.13.4 (17E202)
  2. Browser and version: Chrome 66.0.3359.181

.babelrc

{
  "presets": [
    [
      "@babel/preset-env",
    	{
        "modules": false,
        "useBuiltIns": "usage",
        "forceAllTransforms": false,
        "ignoreBrowserslistConfig": false,
        "debug": true
      }
    ]
  ],
  "plugins": [
    "@babel/plugin-proposal-object-rest-spread",
    "@babel/plugin-syntax-dynamic-import",
    ["@babel/plugin-proposal-class-properties", { "loose": false }],
    ["babel-plugin-transform-react-jsx", { "pragma":"h" }]
  ],
  "env": {
    "development": {
      "plugins": [
        "react-hot-loader/babel"
      ]
    },
    "testing": {
    },
    "staging": {
    },
    "production": {
    }
  }
}

defining the hotness

/* global __DEVELOPMENT__ */

// PREACT
/* eslint-disable import/first */
// preactSetupRHL.js holds https://github.com/gaearon/react-hot-loader#preact
if (__DEVELOPMENT__) { require('./preactSetupRHL.js'); }
import {h, render} from 'preact';
import AppIndexPreact from 'app/AppIndexPreact.js';

export function preactLazy () {
  console.log(__filename, '[preactLazy] starting');

  let root = null;
  function init () {
    root = render(<AppIndexPreact />, document.querySelector('.index'), root);
  }
  if (__DEVELOPMENT__ && module.hot) {
    console.log(__filename, '[preactLazy] is hot');
    require('preact/devtools');
    module.hot.accept('app/AppIndexPreact.js', () => requestAnimationFrame(init));
  }
  init();
}

launching the hotness

const igniteLazy = () => {
  import(/* webpackChunkName: "index.lazy" */ './index.lazy.js').then((module) => {
    module.preactLazy();
  }).catch((error) => {
    console.log('An error occurred while loading lazy index', error);
  });
};

igniteLazy();

Thanks! 🙇

@theKashey
Copy link
Collaborator

Thanks! I forget that Preact could do it.

@theKashey
Copy link
Collaborator

v4.3.1

@kroko
Copy link
Author

kroko commented Jun 9, 2018

Morning. That was fast, thanks! 😄

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants