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
Closed

Add Hooks API #1247

kossnocorp opened this issue Oct 25, 2018 · 42 comments

Comments

@kossnocorp
Copy link

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
Copy link

Would pee my pants with happiness!

@developit
Copy link
Member

developit 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
Copy link

huozhi commented Nov 3, 2018

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

@arusanov
Copy link

arusanov 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
Copy link

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
Copy link
Contributor

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
Copy link

hugmanrique commented Nov 10, 2018

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

@arusanov
Copy link

While treeshaking will remove some, It won't be able to remove this code for example:
https://github.com/developit/preact/blob/master/src/vdom/component.js#L27
or this one
https://github.com/developit/preact/blob/master/src/vdom/component.js#L86
or this
https://github.com/developit/preact/blob/master/src/vdom/component.js#L200

@AlexGalays
Copy link
Contributor

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
Copy link
Member

@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
Copy link
Contributor

@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
Copy link
Member

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

@developit
Copy link
Member

developit 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
Copy link
Contributor

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

@AlexGalays
Copy link
Contributor

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

@andria-dev
Copy link

Any update on hooks status?

@a1pack
Copy link

a1pack commented Nov 29, 2018

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

@skdigital
Copy link

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

@pelotom
Copy link

pelotom commented Dec 18, 2018

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

@skdigital
Copy link

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

@developit
Copy link
Member

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
Copy link
Member

@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
Copy link

thadeu commented Jan 7, 2019

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

@developit
Copy link
Member

developit 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>;
}

@yisar
Copy link

yisar 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
Copy link

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

@yisar
Copy link

yisar 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
Copy link

a1pack 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
Copy link

a1pack 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
Copy link
Member

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
Copy link

Anwardo 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
Copy link
Member

marvinhagemeister 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
Copy link
Member

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
Copy link

@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
Copy link
Member

@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
Copy link
Member

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
Copy link

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

@marvinhagemeister
Copy link
Member

@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
Copy link

dandv 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
Copy link
Member

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

@dandv
Copy link

dandv commented May 22, 2019

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

TypeError: Cannot read property 'replace' of undefined

image

@ForsakenHarmony
Copy link
Member

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
Projects
None yet
Development

No branches or pull requests