amplify-js icon indicating copy to clipboard operation
amplify-js copied to clipboard

`Hub.listen` not firing when inside `useEffect`

Open cekpowell opened this issue 9 months ago • 20 comments

Before opening, please confirm:

JavaScript Framework

Next.js

Amplify APIs

Authentication

Amplify Version

v6

Amplify Categories

auth

Backend

Other

Environment information

# Put output below this line

  System:
    OS: macOS 14.0
    CPU: (12) arm64 Apple M2 Pro
    Memory: 118.72 MB / 16.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 18.18.2 - ~/.nvm/versions/node/v18.18.2/bin/node
    Yarn: 1.22.19 - /usr/local/bin/yarn
    npm: 9.8.1 - ~/.nvm/versions/node/v18.18.2/bin/npm
    Watchman: 2024.05.02.00 - /opt/homebrew/bin/watchman
  Browsers:
    Chrome: 125.0.6422.78
    Safari: 17.0
  npmPackages:
    @ampproject/toolbox-optimizer:  undefined ()
    @aws-amplify/adapter-nextjs: ^1.2.1 => 1.2.1 
    @aws-amplify/adapter-nextjs/api:  undefined ()
    @aws-amplify/adapter-nextjs/data:  undefined ()
    @babel/core:  undefined ()
    @babel/runtime:  7.22.5 
    @edge-runtime/cookies:  4.1.1 
    @edge-runtime/ponyfill:  2.4.2 
    @edge-runtime/primitives:  4.1.0 
    @emotion/react: ^11.11.4 => 11.11.4 
    @emotion/styled: ^11.11.5 => 11.11.5 
    @hapi/accept:  undefined ()
    @hookform/resolvers: ^3.4.2 => 3.4.2 
    @hookform/resolvers/ajv:  1.0.0 
    @hookform/resolvers/arktype:  1.0.0 
    @hookform/resolvers/class-validator:  1.0.0 
    @hookform/resolvers/computed-types:  1.0.0 
    @hookform/resolvers/effect-ts:  1.0.0 
    @hookform/resolvers/io-ts:  1.0.0 
    @hookform/resolvers/joi:  1.0.0 
    @hookform/resolvers/nope:  1.0.0 
    @hookform/resolvers/superstruct:  1.0.0 
    @hookform/resolvers/typanion:  1.0.0 
    @hookform/resolvers/typebox:  1.0.0 
    @hookform/resolvers/valibot:  1.0.0 
    @hookform/resolvers/vest:  1.0.0 
    @hookform/resolvers/yup:  1.0.0 
    @hookform/resolvers/zod:  1.0.0 
    @mswjs/interceptors:  undefined ()
    @mui/material: ^5.15.17 => 5.15.17 
    @napi-rs/triples:  undefined ()
    @next/font:  undefined ()
    @opentelemetry/api:  undefined ()
    @svgr/webpack: ^8.1.0 => 8.1.0 
    @trivago/prettier-plugin-sort-imports: ^4.3.0 => 4.3.0 
    @types/eslint: 8.56.5 => 8.56.5 
    @types/node: ^20 => 20.12.12 
    @types/react: ^18 => 18.3.2 
    @types/react-dom: ^18 => 18.3.0 
    @types/voca: ^1.4.5 => 1.4.5 
    @typescript-eslint/eslint-plugin: 7.9.0 => 7.9.0 
    @typescript-eslint/parser: ^7.9.0 => 7.9.0 (7.2.0)
    @vercel/nft:  undefined ()
    @vercel/og:  0.6.2 
    acorn:  undefined ()
    amphtml-validator:  undefined ()
    anser:  undefined ()
    arg:  undefined ()
    assert:  undefined ()
    async-retry:  undefined ()
    async-sema:  undefined ()
    aws-amplify: ^6.3.4 => 6.3.4 
    aws-amplify/adapter-core:  undefined ()
    aws-amplify/analytics:  undefined ()
    aws-amplify/analytics/kinesis:  undefined ()
    aws-amplify/analytics/kinesis-firehose:  undefined ()
    aws-amplify/analytics/personalize:  undefined ()
    aws-amplify/analytics/pinpoint:  undefined ()
    aws-amplify/api:  undefined ()
    aws-amplify/api/server:  undefined ()
    aws-amplify/auth:  undefined ()
    aws-amplify/auth/cognito:  undefined ()
    aws-amplify/auth/cognito/server:  undefined ()
    aws-amplify/auth/enable-oauth-listener:  undefined ()
    aws-amplify/auth/server:  undefined ()
    aws-amplify/data:  undefined ()
    aws-amplify/data/server:  undefined ()
    aws-amplify/datastore:  undefined ()
    aws-amplify/in-app-messaging:  undefined ()
    aws-amplify/in-app-messaging/pinpoint:  undefined ()
    aws-amplify/push-notifications:  undefined ()
    aws-amplify/push-notifications/pinpoint:  undefined ()
    aws-amplify/storage:  undefined ()
    aws-amplify/storage/s3:  undefined ()
    aws-amplify/storage/s3/server:  undefined ()
    aws-amplify/storage/server:  undefined ()
    aws-amplify/utils:  undefined ()
    babel-packages:  undefined ()
    browserify-zlib:  undefined ()
    browserslist:  undefined ()
    buffer:  undefined ()
    bytes:  undefined ()
    ci-info:  undefined ()
    cli-select:  undefined ()
    client-only:  0.0.1 
    commander:  undefined ()
    comment-json:  undefined ()
    compression:  undefined ()
    conf:  undefined ()
    constants-browserify:  undefined ()
    content-disposition:  undefined ()
    content-type:  undefined ()
    cookie:  undefined ()
    cross-spawn:  undefined ()
    crypto-browserify:  undefined ()
    cspell: ^8.8.1 => 8.8.1 
    css.escape:  undefined ()
    data-uri-to-buffer:  undefined ()
    debug:  undefined ()
    devalue:  undefined ()
    domain-browser:  undefined ()
    edge-runtime:  undefined ()
    eslint: ^8 => 8.57.0 
    eslint-config-next: 14.2.3 => 14.2.3 
    eslint-config-prettier: ^9.0.0 => 9.1.0 
    eslint-plugin-ft-flow: 2.0.3 => 2.0.3 
    eslint-plugin-jest: 28.5.0 => 28.5.0 
    eslint-plugin-jsx-expressions: 1.3.2 => 1.3.2 
    eslint-plugin-prettier: 5.1.3 => 5.1.3 
    eslint-plugin-react-hooks: 4.6.2 => 4.6.2 
    events:  undefined ()
    find-cache-dir:  undefined ()
    find-up:  undefined ()
    fresh:  undefined ()
    get-orientation:  undefined ()
    glob:  undefined ()
    gzip-size:  undefined ()
    http-proxy:  undefined ()
    http-proxy-agent:  undefined ()
    https-browserify:  undefined ()
    https-proxy-agent:  undefined ()
    husky: ^9.0.11 => 9.0.11 
    icss-utils:  undefined ()
    ignore-loader:  undefined ()
    image-size:  undefined ()
    is-animated:  undefined ()
    is-docker:  undefined ()
    is-wsl:  undefined ()
    jest-worker:  undefined ()
    json5:  undefined ()
    jsonwebtoken:  undefined ()
    jwt-decode: 3.1.2 => 3.1.2 
    lint-staged: ^15.2.2 => 15.2.2 
    loader-runner:  undefined ()
    loader-utils:  undefined ()
    lodash.curry:  undefined ()
    lottie-react: ^2.4.0 => 2.4.0 
    lru-cache:  undefined ()
    mini-css-extract-plugin:  undefined ()
    nanoid:  undefined ()
    native-url:  undefined ()
    neo-async:  undefined ()
    next: 14.2.3 => 14.2.3 
    next-intl: ^3.14.0 => 3.14.0 
    node-fetch:  undefined ()
    node-html-parser:  undefined ()
    ora:  undefined ()
    os-browserify:  undefined ()
    p-limit:  undefined ()
    path-browserify:  undefined ()
    picomatch:  undefined ()
    platform:  undefined ()
    postcss-flexbugs-fixes:  undefined ()
    postcss-modules-extract-imports:  undefined ()
    postcss-modules-local-by-default:  undefined ()
    postcss-modules-scope:  undefined ()
    postcss-modules-values:  undefined ()
    postcss-preset-env:  undefined ()
    postcss-safe-parser:  undefined ()
    postcss-scss:  undefined ()
    postcss-value-parser:  undefined ()
    prettier: ^3.2.5 => 3.2.5 
    process:  undefined ()
    punycode:  undefined ()
    querystring-es3:  undefined ()
    raw-body:  undefined ()
    react: ^18 => 18.3.1 
    react-builtin:  undefined ()
    react-device-detect: ^2.2.3 => 2.2.3 
    react-dom: ^18 => 18.3.1 
    react-dom-builtin:  undefined ()
    react-dom-experimental-builtin:  undefined ()
    react-experimental-builtin:  undefined ()
    react-hook-form: ^7.51.5 => 7.51.5 
    react-is:  18.2.0 
    react-markdown: ^9.0.1 => 9.0.1 
    react-qr-code: ^2.0.13 => 2.0.13 
    react-refresh:  0.12.0 
    react-server-dom-turbopack-builtin:  undefined ()
    react-server-dom-turbopack-experimental-builtin:  undefined ()
    react-server-dom-webpack-builtin:  undefined ()
    react-server-dom-webpack-experimental-builtin:  undefined ()
    regenerator-runtime:  0.13.4 
    sass-loader:  undefined ()
    scheduler-builtin:  undefined ()
    scheduler-experimental-builtin:  undefined ()
    schema-utils:  undefined ()
    semver:  undefined ()
    send:  undefined ()
    server-only:  0.0.1 
    setimmediate:  undefined ()
    sharp: 0.32.6 => 0.32.6 
    shell-quote:  undefined ()
    source-map:  undefined ()
    source-map08:  undefined ()
    stacktrace-parser:  undefined ()
    stream-browserify:  undefined ()
    stream-http:  undefined ()
    string-hash:  undefined ()
    string_decoder:  undefined ()
    strip-ansi:  undefined ()
    superstruct:  undefined ()
    svgo: ^3.3.2 => 3.3.2 
    tar:  undefined ()
    terser:  undefined ()
    text-table:  undefined ()
    timers-browserify:  undefined ()
    tty-browserify:  undefined ()
    typescript: ^5 => 5.4.5 
    ua-parser-js:  undefined ()
    unistore:  undefined ()
    util:  undefined ()
    vm-browserify:  undefined ()
    voca: ^1.4.1 => 1.4.1 
    watchpack:  undefined ()
    web-vitals:  undefined ()
    webpack:  undefined ()
    webpack-sources:  undefined ()
    ws:  undefined ()
    zod: ^3.23.8 => 3.23.8 ()
  npmGlobalPackages:
    @aws-amplify/cli: 12.11.1
    corepack: 0.19.0
    dotenv-cli: 7.4.2
    firebase-tools: 12.0.0
    get-graphql-schema: 2.1.2
    ios-deploy: 1.12.2
    jest: 29.7.0
    npm: 9.8.1
    serverless: 3.38.0
    vercel: 34.1.14

Describe the bug

TLDR

If i place a Hub.listen into a useEffect inside a component, the Hub never fires any events, and so I cannot handle the events and update my state accordingly. If i take the Hub out of the useEffect, it correctly fires, but I cannot update component state from outside of the useEffect as the component has not yet mounted.

Full Description & Context

I have a NextJS app that uses the Amplify SDK to handle Authentication. I am not using the Amplify CLI, but connecting to an existing AWS backend I have defined.

I have implemented sign in via social providers (Google, Apple and Facebook), and I am successfully re-directed to the provider, able to sign in, and be re-directed back to the app. Now, I would like to listen for the redirect auth event in my app so that I can update my system auth state (managed in a context) with the user's details, or handle errors if there are any, and then re-direct the user to the next screen.

As per the docs, I am trying to do this with a Hub.listen inside a useEffect in the page component. However, no event is ever fired when I am re-directed back to the app. If I take the Hub.listen out of a useEffect, or out of the component all together, then the event is fired, but I am no longer able to update my system context (as this must be done inside a component after mounting).

I am guessing the event is not firing inside useEffect because the app is unmounted when the redirect takes place, but then this raises the question of how I am meant to listen to re-direct auth events using the hub?

I have found this existing issue which has been closed, but recent comments suggest others are still facing this problem.

Expected behavior

The Hub listener should fire an event for signInWithRedirect.

Reproduction steps

  • Setup a NextJS app with amplify auth.
  • On your login screen, place a useEffect and a Hub listener which just logs the incoming payload, as done in the docs here. Also, place a Hub listener outside of the useEffect.
  • Call signInWithRedirect, and when redirected back to the app after sign in, the hub in the useEffect will not fire any events, but the one inside the useEffect will.

Code Snippet

// Put your code below this line.

Log output

// Put your logs below this line


aws-exports.js

No response

Manual configuration

No response

Additional configuration

No response

Mobile Device

No response

Mobile Operating System

No response

Mobile Browser

No response

Mobile Browser Version

No response

Additional information and screenshots

No response

cekpowell avatar May 27 '24 22:05 cekpowell