dennisreimann / uiengine

Workbench for UI-driven development
https://dennisreimann.github.io/uiengine/
MIT License
368 stars 25 forks source link

React Hooks not working #46

Closed MrAvantiC closed 5 years ago

MrAvantiC commented 5 years ago

Hey Dennis!

Describe the bug I have a minimal example to reproduce the problem here: https://github.com/MrAvantiC/uiengine-hooks It contains a simple functional component Footer that is supposed to set a counter using React Hooks. But if you start up the development mode and visit http://localhost:3000/_variants/_default/Footer/Footer.jsx-1.html you can see the an error in the console:

Uncaught Invariant Violation: Invalid hook call. Hooks can only be called inside of the body of a function component.

I checked the common mistakes that lead to this error:

:white_check_mark: You might have mismatching versions of React and React DOM. :white_check_mark: You might have more than one copy of React in the same app.

$ npm ls react
uiengine@1.0.0
└── react@16.8.6

$ npm ls react-dom
uiengine@1.0.0
└── react-dom@16.8.6

✅ Call them at the top level in the body of a function component.

export default function Footer(props) {
  const [count, setCount] = useState(0)

That should be fine. And if I use the exact same code inside an application setup with create-react-app it works fine, see this repository: https://github.com/MrAvantiC/hooks-example

To Reproduce

  1. Clone https://github.com/MrAvantiC/uiengine-hooks
  2. Install dependencies
  3. Run npm run dev
  4. Visit http://localhost:3000/_variants/_default/Footer/Footer.jsx-1.html
  5. See console

Expected behavior Should be able to update state using hooks

Regards, René

dennisreimann commented 5 years ago

I have a vague idea what might be wrong here: The page indeed might contains two bundles which each have a separate React (though both use the same version). One is coming from the clientRender file and one from the variant. They are build and included as separate files, so this might be the source of this error – I don't know enough about React hooks in particular, but I can imagine that that is the culprit here.

Please upgrade to the latest versions (core: 2.4.1, webpack: 2.4.0) and you will get better error output, as the js contents aren't embeded as a base64 encoded blob in the HTML anymore.

This was my initial thought, nevertheless I applied the test for a duplicate react import and it works for me (outputs true). So this does not seem to be the error.

We must be Breaking the Rules of Hooks here, even though I don't know why. (I have no further knowledge about hooks though as I haven't used them yet) To me it looks like the useState statement leads to a general error and the DOM not being able to get hydrated – see the following console output that also shows the rerendering error.

Changing this line makes the rerendering work:

// const [count, setCount] = useState(0)
const [count, setCount] = [0, (ct) => ct]  

hooks-error

dennisreimann commented 5 years ago

See the example here: https://uiengine-sample-project.uix.space/testcases/examples/ReactHooks/

dennisreimann commented 5 years ago

v2.5 is available now and fixes this :)