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

Using React Hooks in React Native #21967

Open
theluk opened this Issue Oct 26, 2018 · 100 comments

Comments

Projects
None yet
@theluk

theluk commented Oct 26, 2018

Environment

[skip envinfo]
OS: Windows 10
Node: 10.11.0
Yarn: Not Found
npm: 6.4.1
Watchman: Not Found
Xcode: N/A
Android Studio: Version 3.2.0.0 AI-181.5540.7.32.5056338

Packages: (wanted => installed)
react: 16.7.0-alpha.0 => 16.7.0-alpha.0
react-native: https://github.com/expo/react-native/archive/sdk-30.0.0.tar.gz => 0.55.4
expo: 2.2.0

Description

When using React Hooks like useState within a function component, I get the following error message.

hooks can only be called inside the body of a function component

export default function RootContainer(props) {
  const [something, setSomething] = useState('nothing');

  return (
    <View />
  );
};
@react-native-bot

This comment was marked as outdated.

Collaborator

react-native-bot commented Oct 26, 2018

Can you run react-native info and edit your issue to include these results under the Environment section?

If you believe this information is irrelevant to the reported issue, you may write [skip envinfo] under Environment to let us know.

@brunolemos

This comment has been minimized.

Contributor

brunolemos commented Oct 27, 2018

I was not able to make it work on react-native as well, but with a different error:

TypeError: dispatcher.useState is not a function

hooks can only be called inside the body of a function component

I noticed that this error also happens when you have two different instances of React being used, so double check that. (facebook/react#13991)

@chrisbianca

This comment has been minimized.

chrisbianca commented Oct 27, 2018

I started looking into this yesterday and it seems that the React Native renderer needs to be updated to implement something similar to what has been added for React Dom: https://github.com/facebook/react/pull/13968/files#diff-72f7665306d50674917de18af012bc5b

Currently the React Native renderer only exports the readContext method on it's Dispatcher: https://github.com/facebook/react-native/blob/master/Libraries/Renderer/oss/ReactNativeRenderer-dev.js#L13485

I didn't look into the actual implementation details to see whether this is an easy port as it looks like there's multiple versions of the renderers - both the current and Fabric version of the renderer have a dev, prod and profiling version. I'm assuming these are generated in some way from a single base file for each version (current / Fabric) which isn't available in the repo.

@developer239

This comment has been minimized.

developer239 commented Oct 27, 2018

😢😭

@hramos

This comment has been minimized.

Contributor

hramos commented Oct 28, 2018

We need to update the React Native Renderer inside the Libraries/Renderer directory alongside the React dependency. Please wait for the React sync to land, and we will cut a new official release with 16.6 then. We’ll do the same once 16.7 stable is released.

@brunolemos

This comment has been minimized.

Contributor

brunolemos commented Oct 28, 2018

We’ll do the same once 16.7 stable is released.

It would be much appreciated to have a next version of react-native synced with the next version of react so we can try hooks, concurrent and any other new feature together with everyone else.

My project is universal (same components between web and mobile) so my hands are tied. Can't use hooks or simply upgrade because react-native breaks.

@gaearon

This comment has been minimized.

Member

gaearon commented Oct 28, 2018

We can just do a sync with enableHooks: false feature flag and then those who want can override it locally.

@ferrannp

This comment has been minimized.

Contributor

ferrannp commented Oct 29, 2018

We’ll do the same once 16.7 stable is released.

@hramos React team ask to the community to try hooks and give feedback about them. IMO we need a way for RN people to be able to provide this feedback too (not only React projects) before anything is stable.

@fungilation

This comment has been minimized.

fungilation commented Oct 29, 2018

Hooks is quite a change for React / RN syntax. A lot of docs will need updating too?

@hramos

This comment has been minimized.

Contributor

hramos commented Oct 29, 2018

Using Hooks in React Native

If you'd like to try out Hooks today, you can do the following after installing React 16.7.0-alpha in your project:

Note: Hooks are an experimental proposal to React. You can learn more in @gaearon's post, Making Sense of React Hooks.

  1. Clone the https://github.com/facebook/react repository.
  2. Navigate to the react directory.
  3. Replace all instances of enableHooks = false with enableHooks = true in packages/shared.
  4. Run yarn install
  5. Run yarn build -- --type=RN_OSS.
  6. After a few seconds, you'll notice a new build/react-native/ directory has been created. Copy the contents of this directory, to your project's node_modules/react-native/Libraries/Renderer directory.

Let us know if the above steps work out for you.


We're planning on landing support for React 16.6.0 in 0.57.5. Hooks is available in the 16.7.0-alpha, and feedback from the community so far has been that upgrading to alphas of React in the stable React Native releases can be disruptive. What do people here think about a React Native 0.57.5-alpha release that includes support for 16.7.0-alpha out of the box?

@hramos hramos changed the title from React Hooks not working to Using React Hooks in React Native Oct 29, 2018

@dabit3

This comment has been minimized.

Contributor

dabit3 commented Oct 30, 2018

Thanks @hramos for this info! So this works fine when using useState, but for some reason when I move on to try useEffect I get the following error:

failed to execute 'postMessage' on 'DedicatedWorkerGlobalScope': No function was found that matched the signature provided.

Any ideas on what could be causing this or how to mitigate?

UPDATE This only throws when remote debugger is enabled.

@jlongster

This comment has been minimized.

jlongster commented Oct 30, 2018

Wouldn't it be something like a 0.57.6-alpha if you're already aiming for a stable 0.57.5?

I'm totally fine using a custom build for React Native, as long as it works. Haven't tried it yet but does the error in the above comment make sense? If it helps I can try it as well.

@Manishalexin

This comment has been minimized.

Manishalexin commented Oct 30, 2018

Thanks @hramos for this info! So this works fine when using useState, but for some reason when I move on to try useEffect I get the following error:

failed to execute 'postMessage' on 'DedicatedWorkerGlobalScope': No function was found that matched the signature provided.

Any ideas on what could be causing this or how to mitigate?

I was able to use useEffect without any issues. Anything in particular that didn't work with useEffect?

@dabit3

This comment has been minimized.

Contributor

dabit3 commented Oct 30, 2018

@Manishalexin Just tried it again with a completely new build, still not working for me.

I've tried useEffect in a couple of different ways, still getting errors on all of them (same error as above).

React Native Environment Info:
    System:
      OS: macOS Sierra 10.12.6
      CPU: x64 Intel(R) Core(TM) i5-7360U CPU @ 2.30GHz
      Memory: 52.84 MB / 8.00 GB
      Shell: 5.2 - /bin/zsh
    Binaries:
      Node: 8.12.0 - ~/.nvm/versions/node/v8.12.0/bin/node
      Yarn: 1.3.2 - /usr/local/bin/yarn
      npm: 6.4.1 - ~/.nvm/versions/node/v8.12.0/bin/npm
    SDKs:
      iOS SDK:
        Platforms: iOS 11.2, macOS 10.13, tvOS 11.2, watchOS 4.2
      Android SDK:
        Build Tools: 23.0.1, 26.0.1, 26.0.2, 26.0.3, 27.0.3
        API Levels: 23, 26, 27
    IDEs:
      Android Studio: 3.0 AI-171.4443003
      Xcode: 9.2/9C40b - /usr/bin/xcodebuild
    npmPackages:
      react: ^16.7.0-alpha.0 => 16.7.0-alpha.0
      react-native: 0.57.4 => 0.57.4
    npmGlobalPackages:
      react-native-cli: 2.0.1

UPDATE This only throws when remote debugger is enabled.

@Manishalexin

This comment has been minimized.

Manishalexin commented Oct 30, 2018

@dabit3 I have the exact same config for npm modules but system-wise I am Mojave and Xcode 12( Shouldn't matter, I presume). And moreover, the error seems service worker related. ( which is weird in vanilla RN project )
I'll quickly try with a fresh project and report back. ( I tried it with an existing project )

@dabit3

This comment has been minimized.

Contributor

dabit3 commented Oct 30, 2018

@Manishalexin did you see my comment about the remote debugger?

@Manishalexin

This comment has been minimized.

Manishalexin commented Oct 30, 2018

@dabit3 Just saw. ( Comment doesn't update till page refresh ).
Can confirm the issue with my build too.

UPDATE: @dabit3 Although we get the error, it still works and the app is connected to the debugger and everything else works as expected if we ignore the error and dismiss the error screen.
(Seems to be just an uncaught error on the func signature def )

@IljaDaderko

This comment has been minimized.

IljaDaderko commented Oct 30, 2018

@hramos Regarding your question of using react alpha in react-native: I am usually freakishly strict about using unstable versions of packages in my projects, but having played with 16.7 alpha this weekend I didn't notice any bugs.

Perhaps an alpha release of react-native including hooks could be a good idea? I assume if hooks go past RFC stage and get implemented, react-native will need a lot of pre-testing and this seems like a feature that people would actually love to start using and testing as early as now?

@jfrolich

This comment has been minimized.

jfrolich commented Oct 30, 2018

An alpha release of react-native would be awesome! I am working on a new app that isn't published yet, and would love to use the new hooks API.

@chrisbianca

This comment has been minimized.

chrisbianca commented Oct 30, 2018

We're planning on landing support for React 16.6.0 in 0.57.5. Hooks is available in the 16.7.0-alpha, and feedback from the community so far has been that upgrading to alphas of React in the stable React Native releases can be disruptive. What do people here think about a React Native 0.57.5-alpha release that includes support for 16.7.0-alpha out of the box?

I think letting people opt in to the React 16.7.0-alpha by way of an alpha release of RN is a great idea.

I've certainly struggled in the past with seeing alpha or even beta releases of React being included as part of a stable React Native release and would find it hard to justify in a more corporate environment. However, for those people who are more adventurous, allowing access to it as an alpha release gives people the best of both worlds.

@hramos

This comment has been minimized.

Contributor

hramos commented Oct 30, 2018

We've been discussing with other core contributors how to best approach this, and we're currently leaning towards focusing on landing support for React 16.6.0 stable on React Native 0.57.5 first. We're expecting 0.57.5 to be released sometime this week.

Once that happens, people who would like to experiment with React Hooks may opt to install the React 16.7.0.alpha on their project and follow the instructions I posted earlier to sync the React Native Renderer with Hooks support to their project.

As React Hooks is expected to remain experimental for a few more months, we believe this approach provides the right mix of allowing you all to opt into React Hooks, without placing additional strain on the release process for the next few months prior to React Hooks potentially reaching stable release status.

@jfrolich

This comment has been minimized.

jfrolich commented Oct 31, 2018

Did someone in the community that followed these steps already publish a temporary package to NPM containing the alpha? Would make it easier for us to try it out by just aliasing. If not, anyone interested in it here? then I’ll try to publish!

@Foveluy

This comment has been minimized.

Foveluy commented Nov 2, 2018

For anyone who suffers from building react-native-renderer, i have done a repo to for it, just download and copy it by following
this instructions , you can play with hooks.

https://github.com/Foveluy/rn-temp-renderer

Edit

it doesn't work after copy those file into renderers.

hooks can only be called inside the body of a function component
@bvaughn

This comment has been minimized.

Contributor

bvaughn commented Nov 28, 2018

Ah, so this is interesting. When I more properly patch scheduler (aka just replace it with the canary release) then the bug goes away when connected to the Chrome debugger, but still happens when I'm not connected.

So the bug happens when the setTimeout branch of scheduler is used but not when the MessageChannel/postMessage branch is used.

But the bug still only happens when I run my gist from Expo. (I can't repro it with the setTimeout branch of scheduler when running from fbsource.)

@bvaughn

This comment has been minimized.

Contributor

bvaughn commented Nov 28, 2018

I think I've found the cause. The setTimeout branch of scheduler is scheduling callbacks on a 5000ms delay. This 5000ms is supposed to be the maximum expiration time, but in this fork it ends up being the minimum callback time (unless another state update forces us to sync-flush pending callbacks). Because useEffect is "passive", the results is that React won't call useEffect until after a few seconds in that branch.

It looks like lowering the timeout delay "fixes" the bug. Not surprisingly, I can also repro this bug with react-dom if I force scheduler to use the setTimeout branch.

I assume we (React team) haven't noticed this because we're typically using the postMessage implementation, but with JSC– React Native ends up using the setTimeout fork.

Unless I'm misreading things, that's the cause. I'll chat with some others on the team to confirm my understanding.

Edit I think this was broken by react commit 4d17c3f which intentionally changed the delay under the (mistaken) assumption that it would only impact unit tests.

Edit 2 I've filed facebook/react/issues/14352 to track this.

Edit 3 This bug impacts Android as well, since React Native uses JavaScriptCore there too.

@jas99

This comment has been minimized.

jas99 commented Nov 29, 2018

Can anybody confirm useEffect bug only affects ios?

@ericvicenti

This comment has been minimized.

Contributor

ericvicenti commented Nov 29, 2018

@jas99, the useEffect bug(s) are reported on Android as well by @slorber here: facebook/react#14352 (comment)

@bvaughn

This comment has been minimized.

Contributor

bvaughn commented Nov 29, 2018

This issue impacts JavaScriptCore, which is what React Native uses on Android as well.

@bvaughn

This comment has been minimized.

Contributor

bvaughn commented Dec 1, 2018

Fix has landed via facebook/react/pull/14358 and will go out with the next release of scheduler.

If it's necessary, we can also do a bugfix release to the current scheduler but I think the number of people this affects is probably very low so I'm not sure how important it is to do that patch release?

@brunolemos

This comment has been minimized.

Contributor

brunolemos commented Dec 1, 2018

@bvaughn awesome 🎉🎉

I know some people that postponed playing with it on react native because of the bug, so maybe make the patch fix? Which should increase the number of testers.

@kevinwolfcr

This comment has been minimized.

kevinwolfcr commented Dec 3, 2018

For the ones having problems with useEffect, I switched to useLayoutEffect (while facebook/react#14358) gets merged, and it works.

@bvaughn

This comment has been minimized.

Contributor

bvaughn commented Dec 3, 2018

Yup, useLayoutEffect is synchronous and so it isn't affected by the timer bug.

@bvaughn

This comment has been minimized.

Contributor

bvaughn commented Dec 3, 2018

react 16.7 has a couple of alphas. The first one depends on scheduler@^0.11.0-alpha but the others all depend on scheduler@^0.12.0-alpha. I'm not sure why this is, but I see that there are some significant changes between the two scheduler alphas– and I feel like back porting my fix to 0.11.0-alpha would require extra work and testing.

So for now, I'm only going to patch fix scheduler@0.12.0-alpha.

To use useEffect in your React Native app safely, just make sure you're using react@^16.7.0-alpha.2 and scheduler@^0.12.0-alpha.3.

The patch release has now been published as scheduler@0.12.0-alpha.3

@brunolemos

This comment has been minimized.

Contributor

brunolemos commented Dec 3, 2018

Thanks @bvaughn! 🎉

It's perfect now.

For anyone else, I made a new build based on react-native@0.57.7:

yarn add react@next react-native@"npm:@brunolemos/react-native"
yarn add --dev @types/react @types/react-native

use yarn upgrade instead of yarn add if you notice the newer version did not get installed

Also add this to your package.json:

"resolutions": {
  "scheduler": "0.12.0-alpha.3"
},

@bvaughn

This comment has been minimized.

Contributor

bvaughn commented Dec 3, 2018

Niiiiice!

@sunnylqm

This comment has been minimized.

Contributor

sunnylqm commented Dec 4, 2018

@brunolemos Thanks for your build, but I think the resolutions part is unnecessary. scheduler@^0.12.0-alpha would be resolved to the latest alpha version.
image

And of course thanks @bvaughn and the react team for the great work!

@brunolemos

This comment has been minimized.

Contributor

brunolemos commented Dec 4, 2018

@sunnylqm I had to do it, maybe because I already had the react next installed. But good to know!

@kevinwolfcr

This comment has been minimized.

kevinwolfcr commented Dec 4, 2018

Awesome, @bvaughn! Do you know if it works with Expo?

@bvaughn

This comment has been minimized.

Contributor

bvaughn commented Dec 4, 2018

Awesome, @bvaughn! Do you know if it works with Expo?

I don't have a lot of Expo experience (in fact, my first time using it was looking into this bug, trying to run the repro) but... why wouldn't it? Any particular reason?

@brunolemos

This comment has been minimized.

Contributor

brunolemos commented Dec 4, 2018

@kevinwolfcr use this and add the yarn resolution, should be enough: https://github.com/expo/sdk-31-with-hooks-experimental

@kevinwolfcr

This comment has been minimized.

kevinwolfcr commented Dec 4, 2018

@bvaughn that's because as Expo runs on its own app, sometimes they do modifications to the react-native package, that's because when you are on an expo project, the dependency react-native its resolved to something from https://github.com/expo/react-native/releases


@brunolemos I am using

"react-native": "https://github.com/expo/react-native/archive/sdk-31-with-hooks-experimental.tar.gz",

on my package.json. Everything works fine, except trying to build the app, which is a huge blocker :(

@josemigallas

This comment has been minimized.

josemigallas commented Dec 10, 2018

@brunolemos I installed your package but useState in undefined.. I get this warning when yarn installing:

warning Resolution field "scheduler@0.12.0-alpha.3" is incompatible with requested version "scheduler@^0.11.0"

However I added the 'resolutions' prop in my package.json. Did you do any other step? 😐
This is my package.json:

{
  "name": "RealmsCounter",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "start": "node node_modules/react-native/local-cli/cli.js start",
    "test": "jest"
  },
  "dependencies": {
    "@brunolemos/react-native": "npm:@brunolemos/react-native",
    "react": "^16.7.0-alpha.2",
    "react-native": "npm:@brunolemos/react-native"
  },
  "devDependencies": {
    "babel-jest": "23.6.0",
    "jest": "23.6.0",
    "metro-react-native-babel-preset": "0.50.0",
    "react-test-renderer": "16.6.1"
  },
  "jest": {
    "preset": "react-native"
  },
  "resolutions": {
    "scheduler": "0.12.0-alpha.3"
  }
}

Also I'm using

yarn 1.12.3
react-native-cli: 2.0.1
react-native: 0.57.7-hooks.1
@bySabi

This comment has been minimized.

bySabi commented Dec 10, 2018

@josemigallas I think scheduler was update on latest react-native RC 0.58.0-rc.1

test it again with:
yarn add react-native@next

@kelset kelset pinned this issue Dec 14, 2018

@alk831

This comment has been minimized.

alk831 commented Dec 14, 2018

How do I solve this issue? Im using 0.57.8 version of React Native, 16.7.0-alpha.0 v of React and React Test Renderer and I don't know what causes this error.

@woodpav

This comment has been minimized.

woodpav commented Dec 14, 2018

@alk831 Make sure you replace all instances of enableHooks = false with enableHooks = true in react/packages/shared before running yarn build -- --type=RN_OSS

@brunolemos

This comment has been minimized.

Contributor

brunolemos commented Dec 14, 2018

I've been using Hooks in production with zero problems so far!
Using this method I posted earlier.

You can check the source code here and the iOS app here. Haven't published the Android app yet.

@hramos hramos added the React label Dec 14, 2018

@rmilejcz

This comment has been minimized.

rmilejcz commented Dec 14, 2018

@brunolemos thanks for that, it works great even useEffect is working. Do you plan on keeping that repo up to date with new rn releases? Thanks again!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment