preactjs / preact

⚛️ Fast 3kB React alternative with the same modern API. Components & Virtual DOM.
https://preactjs.com
MIT License
36.74k stars 1.95k forks source link

Build fails when using hooks #1321

Closed flppv closed 5 years ago

flppv commented 5 years ago

Hey!

First of all, thank you for a great work on updating Preact, was waiting for it and totally satisfied!

I have a weird issue when trying to build my app, which is already full of hooks:

Unable to read file: /Users/.../src/node_modules/preact/hooks/dist/hooks.mjs

TypeError: Cannot read property '__H' of undefined

When in a dev mode, everything works like a charm.

I tried to build without prerender, it didn't help :(

Any ideas on what it could be? Or maybe anyone have built preact@10 app successfully?

developit commented 5 years ago

Hi @flppv! This is most likely an issue with Webpack's handling of JS Modules. It might be worth trying out this webpack plugin to see if that fixes the production build.

Any chance you could set up a reproduction? I'll be trying, but it'd be great if you had something handy.

TimPetricola commented 5 years ago

Hey, I had the exact same issue (in a CRA app), and the plugin suggested by @developit fixes the error :)

danieldiekmeier commented 5 years ago

If #1331 is the same error, then it has a repro at https://github.com/weijarz/preact-x-bug-r-is-undefined

flppv commented 5 years ago

@developit

It might be worth trying out this webpack plugin to see if that fixes the production build.

I'd like not to eject this project if possible. (My project was created with preact-cli)

Any chance you could set up a reproduction?

Sure, just: 1) Use hooks somewhere in the app 2) Run npm run build or preact build 3) Error

@danieldiekmeier yup, indeed that error, but in my case everything works fine when I run npm run dev

38elements commented 5 years ago

Using Rollup can build.

marvinhagemeister commented 5 years ago

Fixed with #1425 :tada:

westtrade commented 5 years ago

Same bug with Parcel build preact - 10.0.0-rc.0

Chrome

index.js:63 Uncaught TypeError: Cannot read property '__H' of undefined
    at c (index.js:63)
    at v (index.js:105)
    at p.App [as constructor] (App.jsx:26)
    at p.z [as render] (options.js:2)
    at P (component.js:63)
    at g (index.js:260)
    at P (component.js:63)
    at g (index.js:260)
    at P (component.js:63)
    at g (index.js:260)

Firefox

TypeError: r is undefined
marvinhagemeister commented 5 years ago

@westtrade Do you happen to have an incorrect import like preact/hooks/src instead of preact/hooks somewhere in your application?

braco commented 5 years ago

This was fixed for me by installing preact-cli@rc

didymu5 commented 5 years ago

I'm having the same issue as @westtrade building with preact-cli widget template. I initially reported it in https://github.com/preactjs/preact/issues/1373

"devDependencies": {
    "eslint": "^4.5.0",
    "identity-obj-proxy": "^3.0.0",
    "if-env": "^1.0.0",
    "jest": "^21.2.1",
    "microbundle": "^0.6.0",
    "node-sass": "^4.5.3",
    "preact-cli": "^2.0.2",
    "preact-widget-scripts": "^0.6.0",
    "sass-loader": "^6.0.6"
  },
  "dependencies": {
    "preact": "^10.0.0-rc.1",
    "preact-compat": "^3.17.0",
    "preact-habitat": "^3.1.0",
    "preact-render-to-string": "^5.0.6",
    "preact-router": "^2.5.7"
  },
kaidoj commented 5 years ago

Having same issue as @westtrade with version 10.0.0-rc.1. Problem occours when i use

import { h, Component } from 'preact'
import { useReducer } from 'preact/hooks'
import { reducer, initialState, ENLARGE } from '../../../reducers/fontSize'
import './scss/style.scss' 

const [count, dispatch] = useReducer(reducer, initialState)

export default class EnlargeText extends Component {...
"dependencies": {
    "@babel/polyfill": "^7.6.0",
    "preact": "^10.0.0-rc.1",
    "preact-render-to-string": "^5.0.6"
  },
 "devDependencies": {
    "@babel/cli": "^7.6.0",
    "@babel/core": "^7.6.0",
    "@babel/plugin-transform-react-jsx": "^7.3.0",
    "@babel/preset-env": "^7.6.0",
    "autoprefixer": "^8.0.0",
    "babel-loader": "^8.0.6",
    "chai": "^4.0.2",
    "copy-webpack-plugin": "^4.0.1",
    "core-js": "^2.4.1",
    "cross-env": "^5.0.1",
    "css-loader": "^3.2.0",
    "eslint": "^4.1.0",
    "eslint-plugin-jest": "^21.7.1",
    "eslint-plugin-react": "^7.0.0",
    "fibers": "^3.1.1",
    "file-loader": "^1.1.7",
    "html-webpack-plugin": "^3.0.0",
    "identity-obj-proxy": "^3.0.0",
    "jest": "^25.0.0",
    "json-loader": "^0.5.4",
    "mini-css-extract-plugin": "^0.8.0",
    "mkdirp": "^0.5.1",
    "ncp": "^2.0.0",
    "node-sass": "^4.12.0",
    "offline-plugin": "^5.0.0",
    "optimize-css-assets-webpack-plugin": "^5.0.3",
    "postcss-loader": "^2.0.3",
    "preact-cli": "^3.0.0-rc.5",
    "preact-jsx-chai": "^3.0.0",
    "preact-svg-loader": "^0.2.1",
    "raw-loader": "^0.5.1",
    "regenerator-runtime": "^0.10.3",
    "replace-bundle-webpack-plugin": "^1.0.0",
    "sass": "^1.22.10",
    "sass-loader": "^8.0.0",
    "script-ext-html-webpack-plugin": "^2.0.0",
    "sinon": "^4.2.1",
    "sinon-chai": "^2.9.0",
    "source-map-loader": "^0.2.1",
    "style-loader": "^0.21.0",
    "terser-webpack-plugin": "^2.0.1",
    "uglifyjs-webpack-plugin": "^2.2.0",
    "url-loader": "^1.0.0",
    "webpack": "^4.0.0",
    "webpack-cli": "^3.3.8",
    "webpack-modules": "^1.0.0"
  }
cristianbote commented 5 years ago

Hey @kaidoj would be best if you could share/create a repo with the issue. I'm recommending the repo just because it's gonna be easier to properly run the build.

Due to their functional nature they can be used in functional components and avoid many pitfalls of the [...] https://preactjs.com/guide/v10/hooks

With the above text, it boils down to:

Seems that you're using useReducer outside of a class based component. Can you amend the above and see if it works?

kaidoj commented 5 years ago

Hey @kaidoj would be best if you could share/create a repo with the issue. I'm recommending the repo just because it's gonna be easier to properly run the build.

Due to their functional nature they can be used in functional components and avoid many pitfalls of the [...] https://preactjs.com/guide/v10/hooks

With the above text, it boils down to:

* Use hooks only inside functional component

* Here's an example https://preactjs.com/guide/v10/hooks#usereducer

Seems that you're using useReducer outside of a class based component. Can you amend the above and see if it works?

Hey @cristianbote ! I can confirm that this was it. I missed that sentence in documentation. Thank you for pointing this out. Everything is working fine now.

avbeladiya commented 4 years ago

hello, for me other hooks are working fine , only when i use "useMemo" it shows error

Uncaught TypeError: Cannot read property '__H' of undefined

my hook code

import { useState, useMemo } from "preact/hooks";

const defaultColumn = useMemo(
    () => ({
        Filter: DefaultColumnFilter
    }),
    []
);

not sure why only one hook has issue..

gautam1168 commented 4 years ago

If anyone is doing this using the non-build route and getting the above error, then for me this was happening because the hook module was loading a different version of preact. You should open the https://unpkg.com/preact@latest/hooks/dist/hooks.module.js?module file and look at what preact its importing

import {options as n} from "https://unpkg.com/preact@latest?module";

You should be importing this same preact in your project as well:

import { h } from 'https://unpkg.com/preact@latest?module';

I was getting the above error when importing like this in my project:

import { h } from 'https://unpkg.com/preact?module';
chmelevskij commented 3 years ago

As @gautam1168 mentioned Cannot read property '__H' of undefined" can be happening because of different versions. Sometimes even preact/debug can't catch it.

In my case it was because it was monorepo and packages had different versions.

fluke commented 3 years ago

hello, for me other hooks are working fine , only when i use "useMemo" it shows error

Uncaught TypeError: Cannot read property '__H' of undefined

my hook code

import { useState, useMemo } from "preact/hooks";

const defaultColumn = useMemo(
    () => ({
        Filter: DefaultColumnFilter
    }),
    []
);

not sure why only one hook has issue..

Found that this error happens if useMemo is not exactly inside a functional component, it will throw an error if it's outside and even if it's inside another method.

blipk commented 2 years ago

Hi, I'm getting a similar error:

index.js:103 Uncaught TypeError: Cannot read property '__hooks' of undefined
    at getHookState (index.js:103)
    at useMemo (index.js:209)
    at Object.useRef (index.js:184)
    at Component.Map [as constructor] (app.js:15)
    at Component.doRender [as render] (index.js:515)
    at Object.diff (index.js:181)
    at Object.diffChildren (children.js:136)
    at Object.diff (index.js:196)
    at Object.diffChildren (children.js:136)
    at Object.diff (index.js:196)

Here is my code:

import {$, $$} from './data.ts'
import { h, Component, render } from 'preact'
import { useRef, useState, useEffect } from 'preact/hooks'
import mapboxgl from 'mapbox-gl';
import htm from 'htm'
const html = htm.bind(h);
mapboxgl.accessToken = '';

export default function App (props) {
    return html`<h1>Hello ${props.name}!</h1><${Map} />`
}

export default function Map (props) {
    const mapContainer = useRef(null);
    const map = useRef(null);
    const [lng, setLng] = useState(-70.9);
    const [lat, setLat] = useState(42.35);
    const [zoom, setZoom] = useState(9);

    useEffect(() => {
        if (map.current) return; // initialize map only once
        map.current = new mapboxgl.Map({
            container: mapContainer.current,
            style: 'mapbox://styles/mapbox/streets-v11',
            center: [lng, lat],
            zoom: zoom
        });
    });

    return html`<div>
                    <div ref=${mapContainer} class="map-container" />
                </div>`
}

render(html`<${App} name="X" />`, document.body);

I'm using parcel with this package:

    "scripts": {
        "start": "rm -rf dist && parcel src/index.html",
        "build": "rm -rf build && parcel build --dist-dir build --public-url ."
    },
    "devDependencies": {
        "D": "^1.0.0",
        "parcel": "^2.0.1",
        "preact-cli": "^3.3.2",
        "typescript": "^4.4.4"
    },
    "dependencies": {
        "htm": "^3.1.0",
        "mapbox-gl": "^2.6.1",
        "preact": "^10.6.0"
    }

Could anyone point me in the right direction?

Thanks

EDIT: I tried to import preact/compat instead of preact/hooks and error changes to:

Uncaught TypeError: Cannot read property '__H' of undefined
    at m (index.js:103)
    at A (index.js:209)
    at Object.s (index.js:184)
    at Component.Map [as constructor] (app.js:15)
    at Component.doRender [as render] (index.js:515)
    at Object.diff (index.js:181)
    at Object.diffChildren (children.js:136)
    at Object.diff (index.js:196)
    at Object.diffChildren (children.js:136)
    at Object.diff (index.js:196)
spacebeers commented 2 years ago

Did you ever solve this? Similar issue with Parcel

ericmorand commented 1 year ago

Same issue with Rollup.

krutoo commented 1 year ago

Same issue with rspack

andrewiggins commented 1 year ago

I made a repo showing how to use Preact with a variety of bundlers (webpack, rollup, vite, rspack, parcel): https://github.com/andrewiggins/preact-bundling

All of them work with preact/hooks using a basic Counter example. If you are still having issues, please create a new issue with a repro that we can use to determine what is done differently from these examples to help debug the issue.

krutoo commented 1 year ago

@andrewiggins thanks a lot, but in my case i want to build app that uses preact/compat through esm.sh

i dont now how to configure webpack/rspack to force app to use preact compat from esm.sh

here is the repo with todo: https://github.com/krutoo/preact-compat-rspack-esm-sh

rschristian commented 1 year ago

@krutoo Using a bundler w/ a CDN is a very odd combo. Import maps are likely the way to go though.

krutoo commented 1 year ago

@krutoo Using a bundler w/ a CDN is a very odd combo. Import maps are likely the way to go though.

@rschristian no is not, we bundle only source code of app itself and not bundle vendors