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

Add Hooks API #1247

Closed
kossnocorp opened this issue Oct 25, 2018 · 42 comments

Comments

Projects
None yet
@kossnocorp
Copy link

commented Oct 25, 2018

React team just announced new React Hooks API, and I think it will be a worthy addition to Preact.

The RFC: reactjs/rfcs#68
A blog post at React blog: https://reactjs.org/docs/hooks-intro.html

@4lph4-Ph4un

This comment has been minimized.

Copy link

commented Nov 1, 2018

Would pee my pants with happiness!

@developit

This comment has been minimized.

Copy link
Member

commented Nov 2, 2018

It looks like we're going to be releasing hooks support as an opt-in import, so you only pay for them if you use them. It'll look like this:

import { useState } from 'preact/hooks'

export function Demo(props) {
  const [count, setCount] = useState(0)
  return <button onClick={() => setCount(c => c+1)}>{count}</button>
}

There's been some discussion of this on Twitter - currently we have a working prototype.

@huozhi

This comment has been minimized.

Copy link

commented Nov 3, 2018

@developit is there a current developing branch for hooks feature now?

@arusanov

This comment has been minimized.

Copy link

commented Nov 8, 2018

What if all components stuff can also be moved into opt-in import?
Like import { Component } from 'preact/component'
So if you want to use only functional components and hooks you don't pay for component(Will|Did)...
Sure it's a breaking change but maybe someday...

@hugmanrique

This comment has been minimized.

Copy link

commented Nov 10, 2018

Webpack should already (don't quote me on this) just remove the Component class and all other functions you don't use in your code.

@SolarLiner

This comment has been minimized.

Copy link
Contributor

commented Nov 10, 2018

Only with the proper tree shaking plugins? Or is it part of Webpack now and I've just lost touch (last option most likely)?

@hugmanrique

This comment has been minimized.

Copy link

commented Nov 10, 2018

Webpack 4 does tree shaking in production mode (Source: https://webpack.js.org/guides/tree-shaking/) 😀

@arusanov

This comment has been minimized.

@AlexGalays

This comment has been minimized.

Copy link
Contributor

commented Nov 18, 2018

Moving components into their own sub-package sounds great, especially since they become useless if one go with hooks exclusively. So most projects could decide whether they want the OO style (/components) or the more FP style (/hooks)

@marvinhagemeister

This comment has been minimized.

Copy link
Member

commented Nov 19, 2018

@AlexGalays it's unlikely that they'll become "useless" anytime soon. There are a lot of third-party components on npm and it will take a long time for them to change. And that assumes that all the authors do want to change to hooks in the first place.

@AlexGalays

This comment has been minimized.

Copy link
Contributor

commented Nov 19, 2018

@AlexGalays it's unlikely that they'll become "useless" anytime soon. There are a lot of third-party components on npm and it will take a long time for them to change. And that assumes that all the authors do want to change to hooks in the first place.

Yes, I never wrote that though.

@marvinhagemeister

This comment has been minimized.

Copy link
Member

commented Nov 19, 2018

@AlexGalays Oh sorry, my bad. I misread your comment.

@developit

This comment has been minimized.

Copy link
Member

commented Nov 20, 2018

In order to move Component into a subpackage we'd need to disentangle it from the renderer. Right now it's plumbed directly into the renderer since setState and forceUpdate enqueue rendering. It seems like the only way to remove that direct dependence would be to export a secret member from Preact that can be used to call enqueueRender(). This could potentially be done the same way we do hooks (import {options} from 'preact'; options.enqueueRender()). I'm not sure what the savings would be though.

@AlexGalays

This comment has been minimized.

Copy link
Contributor

commented Nov 20, 2018

Is there a repo/branch for the hooks work in progress?

@AlexGalays

This comment has been minimized.

Copy link
Contributor

commented Nov 22, 2018

No pressure btw, just wondering. Perhaps I could even help :)

@ChrisBrownie55

This comment has been minimized.

Copy link

commented Nov 25, 2018

Any update on hooks status?

@a1pack

This comment has been minimized.

Copy link

commented Nov 29, 2018

Wrote a poc, more like a code to play with until it is available from preact devs

@skdigital

This comment has been minimized.

Copy link

commented Dec 8, 2018

is this currently happening guys? When could we likely we see the new react hooks api available for use in preact?

@pelotom

This comment has been minimized.

Copy link

commented Dec 18, 2018

And what about Suspense, concurrent mode et al? Can Preact really keep up with all these features?

@skdigital

This comment has been minimized.

Copy link

commented Dec 19, 2018

thats a good question... alot of changes happening quite quickly on the react side of things..

@developit

This comment has been minimized.

Copy link
Member

commented Dec 19, 2018

Hooks is happening, yes. A few folks including @AlexGalays are working on it.

Regarding the other changes, Suspense is on the table and is enabled by the fundamental changes being released in Preact X. Concurrent mode seems much less likely to be useful in a 3kB library, but who knows.

@developit

This comment has been minimized.

Copy link
Member

commented Dec 19, 2018

@a1pack your implementation is interesting! If you're able to join the Preact slack to chat with some folks on the core team, I think we might be interested in using pieces of it.

@thadeu

This comment has been minimized.

Copy link

commented Jan 7, 2019

@developit ever thought of adding for unistore instead preact? would be more simply, right?

@developit

This comment has been minimized.

Copy link
Member

commented Jan 9, 2019

@thadeu I'd love to see a hooks version of unistore's connect() function:

import { useStore, useActions } from 'unistore/preact/hooks';
const ACTIONS = store => ({
  setTitle() {},
  navigate(state, url) { return { url } }
});
function Foo() {
  const { url, title } = useStore('url,title');
  const { navigate, setTitle } = useActions(ACTIONS);

  return <button onclick={() => navigate('/foo')}>{title}</button>;
}
@132yse

This comment has been minimized.

Copy link

commented Jan 12, 2019

I'm glad to see this issue. I'm also working on react hooks, and I'm having difficulties.

I'm willing to contribute.

At present, I have achieved the minimum implementation of hooks.
https://github.com/132yse/fre/blob/master/packages/hooks

But the question now is triggering rerender, useState is different form setState, which do not know from which functional component call .

I guess that's related to the React Fiber

@baetheus

This comment has been minimized.

Copy link

commented Jan 14, 2019

Took the experimental @a1pack implementation and added very generic typescript types, encapsulated the implementation in a module, and confirmed that this implementation works with rollup scope hoisting and tree shaking. https://gist.github.com/baetheus/d279ec135c2c54ee2c2b0209f1c8f29a

@132yse

This comment has been minimized.

Copy link

commented Jan 15, 2019

@baetheus @a1pack Your realization is not perfect. setState() will re-render render() that from current component.
If parent component rerender, child component will rerender and state will go back to the initial value

for example:

function App() {
  const [sex, setSex] = useState("boy")
  return (
    <div>
      <h2>{sex}</h2>
      <button onClick={() => setSex(sex === "boy" ? "girl" : "boy")}>x</button>
      <Counter />
    </div>
  )
}

function Counter() {
  const [count, setCount] = useState(0)

  return (
    <div>
      <h1>{count}</h1>
      <button onClick={() => setCount(count + 1)}>+</button>
    </div>
  )
}

when I setSex ,the count will back to 0

@a1pack

This comment has been minimized.

Copy link

commented Jan 18, 2019

That's why we need implementation from preact devs :) Actually I found the same issue by myself but did not had small example to reproduce it. Debugging this behavior I found that Preact unmounts an inner component (Counter in this case) and mounts back again a new instance. Actually it is not the only case where it does not work and how it does not work.

For some cases I did a fix replacing bind with anonymous class (updated POC to reflect this + added licence), but this case and one more very similar (still want to find a time to do small example) still fails.

Not sure if it is caused by POC implementation or it is a Preact bug. But if it is a bug in POC than most probably in the options.vnode even if it looks simplistic already.

Unfortunately did not had time to improve POC a lot. Also I feel like it can be optimized in many places.

In the end I spend just about 40 minutes implementing it but about a day testing and can only confirm that it is not production ready at all.

@a1pack

This comment has been minimized.

Copy link

commented Jan 22, 2019

Updated POc one more time. Now it works, also I don't see problem in my more complex tests. Still left 2 points:

  1. In debugger no good component names (use bind to get them back, but on your own risk)
  2. Does not work in IE (because of WeakMap)
@marvinhagemeister

This comment has been minimized.

Copy link
Member

commented Jan 28, 2019

FYI: The hooks api will be part as an experimental feature of our next major release (titled: Preact X). The PR for it and a second one which optimizes bundle size was merged just before the weekend 🎉

@Anwardo

This comment has been minimized.

Copy link

commented Jan 28, 2019

FYI: The hooks api will be part as an experimental feature of our next major release (titled: Preact X). The PR for it and a second one which optimizes bundle size was merged just before the weekend 🎉

Great news! Dare I ask if there is an ETA on the release of X? 👀It sounds like it's going to be amazing 😃

@marvinhagemeister

This comment has been minimized.

Copy link
Member

commented Jan 28, 2019

@Anwardo We're currently aiming for a beta/rc release around mid February. We'll post an announcement at that time with more info 🎉

@marvinhagemeister

This comment has been minimized.

Copy link
Member

commented Feb 6, 2019

Quick update: We're currently working on adding the last missing piece to hooks wich is the new context api via useContext. We originally didn't plan to include it in the initial release of Preact X but due to popular demand and widespread usage of createContext we decided to include it 👍 The PR's for it are already there and are awaiting review and some size reductions.

The downside is that this will slightly affect the release date. March seems like a more realistic estimate right now 👍

@wizzard0

This comment has been minimized.

Copy link

commented Feb 20, 2019

@marvinhagemeister umm is it possible to peek at the code somewhere? grepping for useState doesn't return anything in developit/preact, developit/* or marvinhagemeister/* :)

@marvinhagemeister

This comment has been minimized.

Copy link
Member

commented Feb 20, 2019

@wizzard0 Preact X currently lives in a private repo but will be merged soon into this one here. The switchover date is March 4th. See: https://mobile.twitter.com/marvinhagemeist/status/1097973028426788864 🎉

@marvinhagemeister

This comment has been minimized.

Copy link
Member

commented Mar 4, 2019

We just merged the PR for Preact X #1302 which includes the hooks addon. An alpha release should be available in a few hours 🎉

@Xeoncross

This comment has been minimized.

Copy link

commented May 1, 2019

Any idea of when the hooks documentation / API reference will be live?

@marvinhagemeister

This comment has been minimized.

Copy link
Member

commented May 1, 2019

@Xeoncross Updating our docs (and our site in general) is on our roadmap, but it's hard to tell when that will be finished. In Preact hooks work exactly the same as in React so their docs for hooks match perfectly. The only difference is the import: preact/hooks vs react 👍 💯

@dandv

This comment has been minimized.

Copy link

commented May 22, 2019

I think I'm running into a compatibility problem with react-wordcloud. Running the example from the readme in a new Preact 8.4.2 app fails with

useRef is not a function

After installing preact@next and adding import { useRef } from 'preact/hooks', the error becomes

preact.js?10a9:1 Uncaught TypeError: Cannot read property 'default' of undefined
at rankChild (preact-router.es.js?bff2:82)
at prepareVNodeForRanking (preact-router.es.js?bff2:65)
at Array.filter ()
at Router.getMatchingChildren (preact-router.es.js?bff2:303)
at Router.render (preact-router.es.js?bff2:326)

Installing preact-compat didn't help.

@ForsakenHarmony

This comment has been minimized.

Copy link
Member

commented May 22, 2019

you want preact/compat, not the old preact-compat

@dandv

This comment has been minimized.

Copy link

commented May 22, 2019

@ForsakenHarmony: after removing preact-compat and installing preact/compat, I get

TypeError: Cannot read property 'replace' of undefined

image

@ForsakenHarmony

This comment has been minimized.

Copy link
Member

commented May 22, 2019

do you have the latest preact-router?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.