facebook / react

The library for web and native user interfaces.
https://react.dev
MIT License
229.16k stars 46.89k forks source link

React 18: having Invalid hook call problem with rendering app wrapped by React.StrictMode #21848

Closed julia-dizhak closed 3 years ago

julia-dizhak commented 3 years ago

I have a problem with rendering app after migrating to 18 version

const root = ReactDOM.createRoot(document.getElementById('root'));
const AppTest = () => <div>test react alpha 18</div>;
root.render(<React.StrictMode><App /></React.StrictMode>)

I have Invalid hook call warning in console node is V14.16.1 installed react alpha via yarn add react@alpha react-dom@alpha

Dependencies

{
  "name": "frontend",
  "version": "1.7.0-0",
  "private": true,
  "scripts": {
    "start": "PORT=8080 ESLINT_NO_DEV_ERRORS=true TSC_COMPILE_ON_ERROR=true react-app-rewired start",
    "build": "ESLINT_NO_DEV_ERRORS=true TSC_COMPILE_ON_ERROR=true DISABLE_ESLINT_PLUGIN=true react-app-rewired build",
    "test": "NODE_ICU_DATA=node_modules/full-icu jest",
    "test:watch": "yarn test --watch",
    "test:coverage": "yarn test --collectCoverage",
    "test:coverage:develop": "yarn test:coverage --changedSince=origin/develop",
    "test:coverage:onlyChanged": "yarn test:coverage --onlyChanged",
    "translation-scan:ci": "i18next-scanner --config i18next-scanner.config.ci.js",
    "type": "tsc --noEmit",
    "type:ci": "tsc --noEmit --project tsconfig.ci.json",
    "type:watch": "tsc --noEmit -w",
    "prettier": "prettier --check --write \"**/*.{js,jsx,ts,tsx}\"",
    "lint": "eslint .",
    "lint:ci": "eslint -c .eslintrc-ci .",
    "lint:fix": "eslint --fix .",
    "lint:css": "stylelint './src/**/*.{js,jsx,ts,tsx}'",
    "stylelint-check": "stylelint-config-prettier-check",
    "storybook": "start-storybook -p 6006",
    "build-storybook": "build-storybook",
    "gql:codegen": "graphql-codegen --config src/types/graphql/codegen.yml",
    "chromatic": "yarn chromatic --project-token 10bde9e90fc3",
    "eject": "react-app-rewired eject"
  },
  "dependencies": {
    "@babel/helper-define-map": "7.13.12",
    "@date-io/moment": "2.10.11",
    "@material-ui/core": "4.11.2",
    "@material-ui/icons": "4.11.2",
    "@material-ui/lab": "4.0.0-alpha.57",
    "@material-ui/pickers": "3.2.10",
    "@material-ui/styles": "4.11.2",
    "@reduxjs/toolkit": "1.5.1",
    "@sentry/react": "6.2.1",
    "@sentry/tracing": "6.2.1",
    "@types/faker": "5.1.7",
    "@types/lodash": "4.14.170",
    "@types/react-helmet": "6.1.1",
    "@types/react-select": "4.0.13",
    "axios": "0.21.1",
    "babel-jest": "26.6.3",
    "camelcase": "6.2.0",
    "case-converter": "1.0.1",
    "chalk": "4.1.1",
    "clsx": "1.1.1",
    "core-js": "3.10.2",
    "data-forge": "1.8.17",
    "date-fns": "2.21.3",
    "expr-eval": "2.0.2",
    "faker": "5.4.0",
    "file-loader": "6.2.0",
    "file-selector": "0.2.4",
    "formik": "2.2.6",
    "full-icu": "1.3.1",
    "graphql": "15.5.0",
    "graphql-tag": "2.11.0",
    "history": "4.10.1",
    "husky": "3.1.0",
    "i18next": "19.9.2",
    "i18next-browser-languagedetector": "4.3.1",
    "i18next-http-backend": "1.2.1",
    "identity-obj-proxy": "3.0.0",
    "is-wsl": "1.1.0",
    "jest-resolve": "24.9.0",
    "jest-watch-typeahead": "0.6.1",
    "js-file-download": "0.4.12",
    "lodash": "4.17.21",
    "lodash.camelcase": "4.3.0",
    "lodash.find": "4.6.0",
    "lodash.findindex": "4.6.0",
    "lodash.get": "4.4.2",
    "lodash.groupby": "4.6.0",
    "lodash.includes": "4.3.0",
    "lodash.isequal": "4.5.0",
    "lodash.omit": "4.5.0",
    "logrocket": "1.0.14",
    "logrocket-react": "4.0.1",
    "mixpanel-browser": "2.41.0",
    "module-resolver": "1.0.0",
    "moment": "2.29.1",
    "moment-timezone": "0.5.33",
    "notistack": "1.0.9",
    "query-string": "6.14.1",
    "react": "^18.0.0-alpha-6bf111772-20210701",
    "react-app-polyfill": "2.0.0",
    "react-app-rewire-styled-components": "3.0.2",
    "react-country-flag": "2.3.0",
    "react-custom-scrollbars": "4.2.1",
    "react-data-grid": "7.0.0-canary.36",
    "react-datasheet": "1.4.9",
    "react-device-detect": "1.17.0",
    "react-dnd": "10.0.2",
    "react-dnd-html5-backend": "10.0.2",
    "react-dom": "^18.0.0-alpha-6bf111772-20210701",
    "react-dropzone": "11.3.2",
    "react-error-boundary": "3.1.1",
    "react-helmet": "6.1.0",
    "react-i18next": "11.8.13",
    "react-inlinesvg": "2.2.2",
    "react-query": "3.12.0",
    "react-redux": "7.2.2",
    "react-router": "5.2.0",
    "react-router-dom": "5.2.0",
    "react-scripts": "4.0.3",
    "react-select": "3.2.0",
    "react-select-event": "5.2.0",
    "react-table": "7.7.0",
    "react-use-intercom": "1.2.0",
    "react-window": "1.8.6",
    "recharts": "2.0.9",
    "redux": "4.0.5",
    "redux-devtools-extension": "2.13.9",
    "redux-form": "8.3.7",
    "redux-thunk": "2.3.0",
    "reselect": "4.0.0",
    "resolve": "1.20.0",
    "semver": "6.0.0",
    "snyk": "1.438.0",
    "socket.io-client": "2.4.0",
    "styled-components": "5.3.0",
    "throttle-debounce": "3.0.1",
    "ts-jest": "26.4.4",
    "ts-pnp": "1.1.2",
    "url-loader": "4.1.1",
    "use-query-params": "1.2.2",
    "uuid": "8.3.2",
    "xlsx": "0.17.0",
    "yup": "0.29.3"
  },
  "devDependencies": {
    "@babel/helper-define-map": "7.13.12",
    "@graphql-codegen/cli": "1.21.4",
    "@graphql-codegen/introspection": "1.18.2",
    "@graphql-codegen/typescript": "1.22.0",
    "@graphql-codegen/typescript-operations": "1.17.16",
    "@storybook/addon-actions": "6.2.9",
    "@storybook/addon-controls": "6.2.9",
    "@storybook/addon-essentials": "6.2.9",
    "@storybook/addon-links": "6.2.9",
    "@storybook/react": "6.2.9",
    "@testing-library/jest-dom": "5.12.0",
    "@testing-library/react": "11.2.7",
    "@testing-library/react-hooks": "7.0.0",
    "@types/gtag.js": "0.0.6",
    "@types/jest": "26.0.23",
    "@types/logrocket-react": "3.0.0",
    "@types/mixpanel-browser": "2.35.6",
    "@types/node": "14.14.44",
    "@types/papaparse": "5.2.5",
    "@types/react": "^17.0.13",
    "@types/react-dom": "^17.0.8",
    "@types/react-redux": "7.1.16",
    "@types/react-router-dom": "5.1.7",
    "@types/react-table": "7.7.1",
    "@types/react-window": "1.8.3",
    "@types/redux-form": "8.3.1",
    "@types/redux-mock-store": "1.0.2",
    "@types/styled-components": "5.1.7",
    "@types/uuid": "8.3.0",
    "@types/yup": "0.29.11",
    "@typescript-eslint/eslint-plugin": "4.15.0",
    "@typescript-eslint/parser": "4.15.0",
    "axios-mock-adapter": "1.19.0",
    "chromatic": "5.9.2",
    "circular-dependency-plugin": "5.2.2",
    "customize-cra": "1.0.0",
    "esbuild": "0.12.12",
    "esbuild-loader": "2.13.1",
    "eslint": "7.19.0",
    "eslint-config-airbnb": "18.2.1",
    "eslint-config-prettier": "6.15.0",
    "eslint-import-resolver-babel-module": "5.3.1",
    "eslint-import-resolver-typescript": "2.4.0",
    "eslint-plugin-fp": "2.3.0",
    "eslint-plugin-import": "2.23.4",
    "eslint-plugin-jest": "24.3.6",
    "eslint-plugin-jsx-a11y": "6.4.1",
    "eslint-plugin-prettier": "3.4.0",
    "eslint-plugin-react": "7.24.0",
    "eslint-plugin-react-hooks": "4.2.0",
    "eslint-plugin-testing-library": "4.6.0",
    "http-proxy-middleware": "1.0.6",
    "i18next-scanner": "2.11.0",
    "i18next-scanner-typescript": "1.0.6",
    "jest-junit": "12.2.0",
    "jest-styled-components": "^7.0.4",
    "jest-svg-transformer": "1.0.0",
    "lint-staged": "11.0.0",
    "prettier": "2.2.1",
    "prop-types": "15.7.2",
    "react-app-rewire-alias": "1.0.2",
    "react-app-rewired": "2.1.8",
    "react-is": "17.0.1",
    "redux-mock-store": "1.5.4",
    "strip-json-comments": "3.1.1",
    "stylelint": "13.12.0",
    "stylelint-config-prettier": "8.0.2",
    "stylelint-config-recommended": "3.0.0",
    "stylelint-config-standard": "18.3.0",
    "stylelint-config-styled-components": "0.1.1",
    "stylelint-processor-styled-components": "1.10.0",
    "typescript": "3.9.7"
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all",
      "ie 11"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version",
      "ie 11"
    ]
  },
  "resolutions": {
    "babel-loader": "8.1.0",
    "**/recharts-scale": "0.4.2"
  },
  "babel": {
    "presets": [
      "react-app"
    ]
  },
  "husky": {
    "hooks": {
      "pre-commit": "yarn lint-staged"
    }
  },
  "snyk": true
}

https://codesandbox.io/s/new

eps1lon commented 3 years ago

Thanks for the feedback.

I suspect that your package manager installed both React 18 and 17. Multiple React versions is one of the reasons for the "invalid hook call" error message.

This might be due to dependencies requiring React 17 via peer dependencies.

What package manager are you using?

bvaughn commented 3 years ago

Hi @julia-dizhak :wave:

Can you help us by providing a link to a CodeSandbox (https://codesandbox.io/s/new), a repository on GitHub, or a minimal code example that reproduces the problem? The info provided isn't sufficient to rule out something like what @eps1lon mentions above.

julia-dizhak commented 3 years ago

hi @bvaughn thanks for taking care here is the sandbox https://codesandbox.io/s/b52q1

React_18_-_CodeSandbox
julia-dizhak commented 3 years ago

Thanks for the feedback.

I suspect that your package manager installed both React 18 and 17. Multiple React versions is one of the reasons for the "invalid hook call" error message.

This might be due to dependencies requiring React 17 via peer dependencies.

What package manager are you using?

hi @eps1lon thanks for support I installed react alpha via yarn add react@alpha react-dom@alpha, node is V14.16.1 As well I deleted node-modules and re-installed peer dependencies

bvaughn commented 3 years ago

Thanks for the repro!

eps1lon commented 3 years ago

hi @bvaughn thanks for taking care here is the sandbox codesandbox.io/s/b52q1

That looks like it's caused by a dev-only logic from styled-components (https://github.com/styled-components/styled-components/issues/3394, https://github.com/styled-components/styled-components/issues/3409) since the reported issue is already reproducible with

import styled from "styled-components";

const StyledPeopleIcon = styled("svg")`
  margin: 10px;
`;

Closing since it's caused by a 3rd party library. The issue is already fixed in https://github.com/styled-components/styled-components/pull/3521 but not released yet.

gaearon commented 3 years ago

Hmm, wait, something isn't right here.

The comments in https://github.com/styled-components/styled-components/pull/3521 claim:

    // If a hook is called outside of a component:
    // React 17 and earlier throw an error
    // React 18 and above use console.error

I don't remember a change like this. I expect we still have a production invariant/error in cases of invalid Hook call.

Can we investigate what the difference is?

gaearon commented 3 years ago

We throw here:

https://github.com/facebook/react/blob/cae635054e17a6f107a39d328649137b83f25972/packages/react-reconciler/src/ReactFiberHooks.new.js#L293-L301

There is a DEV-only console.error here:

https://github.com/facebook/react/blob/cae635054e17a6f107a39d328649137b83f25972/packages/react/src/ReactHooks.js#L26-L40

But it's supposed to throw right afterwards with null access (essentially, null.useState).

Are you saying it doesn't throw anymore?

eps1lon commented 3 years ago

I don't remember a change like this. I expect we still have a production invariant/error in cases of invalid Hook call.

I'm pretty sure this was changed in https://github.com/facebook/react/pull/20604 since I saw the errors shortly after in integration tests with react@next.

Are you saying it doesn't throw anymore?

It does throw but it's no longer clear why without also listening to the console. So the claim is a bit incomplete but sufficient for what we're trying to do: Checking if we're called from inside a function component requires different implementations for React 17 and 18 due to https://github.com/facebook/react/pull/20604

gaearon commented 3 years ago

Ah ok.