eslint-plugin-react-native icon indicating copy to clipboard operation
eslint-plugin-react-native copied to clipboard

[3.9.1] Crash related to <Text>

Open mjmasn opened this issue 3 years ago • 25 comments

Hey! 👋

I'm getting Error: Couldn't find a Program after upgrading this package from 3.8.1 to 3.9.1.

Bit of a contrived example below, but seems to reliably trigger the issue and was just about the smallest repro I could manage to find. Not able to post the actual code we're using I'm afraid but it's essentially rendering something like:

Total: 12.34

Seems to be something to do with nested text that has a function defined somewhere inside. In our case there's a reducer for calculating a total.

Some notes:

  • Using a named fn instead of the arrow fn still crashes - i.e. arr.reduce(function add(acc, value) { return acc + value }, 0)
  • Replacing the reducer callback with something else like a string prevents the crash - i.e. arr.reduce('blah', 0) (obviously invalid code though)
  • Defining the reducer callback outside of the JSX also prevents the crash - i.e. const add = (acc, value) => acc + value and arr.reduce(add, 0) <- looks like this is a reasonable workaround for now...

Repro code:

const Comp = () => {
    return (
        <Text>
            <Text>Text</Text> {fn(() => {})}
        </Text>
    )
}
> eslint .


Oops! Something went wrong! :(

ESLint: 7.8.1

Error: Couldn't find a Program
Occurred while linting /Users/REDACTED/REDACTED/REDACTED.tsx:XX
    at Scope.getProgramParent (/Users/REDACTED/REDACTED/node_modules/@babel/traverse/lib/scope/index.js:813:11)
    at Scope.registerBinding (/Users/REDACTED/REDACTED/node_modules/@babel/traverse/lib/scope/index.js:574:25)
    at Scope.crawl (/Users/REDACTED/REDACTED/node_modules/@babel/traverse/lib/scope/index.js:729:14)
    at Scope.init (/Users/REDACTED/REDACTED/node_modules/@babel/traverse/lib/scope/index.js:709:12)
    at NodePath.setScope (/Users/REDACTED/REDACTED/node_modules/@babel/traverse/lib/path/context.js:131:30)
    at NodePath.setContext (/Users/REDACTED/REDACTED/node_modules/@babel/traverse/lib/path/context.js:147:8)
    at NodePath.pushContext (/Users/REDACTED/REDACTED/node_modules/@babel/traverse/lib/path/context.js:213:8)
    at TraversalContext.visitQueue (/Users/REDACTED/REDACTED/node_modules/@babel/traverse/lib/context.js:100:14)
    at TraversalContext.visitMultiple (/Users/REDACTED/REDACTED/node_modules/@babel/traverse/lib/context.js:79:17)
    at TraversalContext.visit (/Users/REDACTED/REDACTED/node_modules/@babel/traverse/lib/context.js:138:19)

mjmasn avatar Sep 02 '20 15:09 mjmasn

Repro here: https://github.com/mjmasn/eslint-plugin-react-native-270

mjmasn avatar Sep 02 '20 15:09 mjmasn

I got the same issue using the latest version

LRNZ09 avatar Oct 14 '20 09:10 LRNZ09

Same issue when I use @react-native-community/[email protected] which depends on [email protected].

Adding eslint-disable in the file doesn't fix it, so I had to add the file to .eslintignore. Fortunately it was only a single small file for us. 😕

plaa avatar Nov 11 '20 11:11 plaa

+1

eslint error: `> eslint "**/*.{js,ts,tsx}" -o ./eslint-report.txt

Oops! Something went wrong! :(

ESLint: 7.13.0

Error: Couldn't find a Program Occurred while linting /Volumes/T7 Touch/code/react-native-mb-ui/example/src/views/actionsheet/view.tsx:59`

actionsheet/view.tsx:59 <Text onPress={() => setCustomCloseExtra(false)}>取消</Text>

ds147000 avatar Dec 07 '20 03:12 ds147000

Can confirm this happened to me on a larger project. Version 3.10.0 produces the Error: Couldn't find a Program. Downgrading to 3.8.1 fixes this issue (for the time being).

vladev avatar Dec 28 '20 19:12 vladev

Same issue here with [email protected] when trying to use a arrow function inside JSX:

<Button onPress={() => functionWithuseCallback(true)}>Click me</Button>

GrabbenD avatar Mar 16 '21 12:03 GrabbenD

Came up with a workaround :smile:

"rules": {
  "react-native/no-raw-text": "off",
},

GrabbenD avatar Mar 16 '21 13:03 GrabbenD

I'm also getting this error with both arrow functions on onPress and the Text issue. It happens while coding on VSCode by showing a popup with text "ESLint: Couldn't find a Program Occurred while linting..." and also when trying to commit via precommit hooks.

Package.json:

{
  "main": "node_modules/expo/AppEntry.js",
  "scripts": {
    "start": "cross-env COMPONENT_LIBRARY_DEVELOPMENT=false expo start",
    "android": "expo start --android",
    "ios": "expo start --ios",
    "web": "expo start --web",
    "eject": "expo eject",
    "fix": "yarn fix:eslint && yarn fix:prettier",
    "fix:eslint": "eslint \"{src}/**/*.{ts,tsx,js,jsx}\" --fix",
    "fix:prettier": "prettier \"{src}/**/*.{ts,tsx,js,jsx,json}\" --write --config ./.prettierrc.json --ignore-path ./.prettierignore",
    "lint": "eslint --config .eslintrc.json --ignore-path .eslintignore",
    "test": "jest --watchAll",
    "storybook": "start-storybook -p 7007",
    "prestorybook": "rnstl",
    "start:component-library": "cross-env COMPONENT_LIBRARY_DEVELOPMENT=true expo start",
    "build-storybook": "build-storybook",
    "build-static-webapp": "cross-env COMPONENT_LIBRARY_DEVELOPMENT=true expo build:web"
  },
  "jest": {
    "preset": "jest-expo"
  },
  "dependencies": {
    "@expo/vector-icons": "^12.0.0",
    "@react-native-community/masked-view": "0.1.10",
    "@react-navigation/bottom-tabs": "5.11.2",
    "@react-navigation/native": "~5.8.10",
    "@react-navigation/stack": "~5.12.8",
    "cross-env": "^7.0.3",
    "expo": "~40.0.0",
    "expo-asset": "~8.2.1",
    "expo-constants": "~9.3.0",
    "expo-firebase-recaptcha": "^1.3.0",
    "expo-font": "~8.4.0",
    "expo-linking": "~2.0.0",
    "expo-splash-screen": "~0.8.0",
    "expo-status-bar": "~1.0.3",
    "expo-web-browser": "~8.6.0",
    "firebase": "^8.3.1",
    "react": "16.13.1",
    "react-dom": "16.13.1",
    "react-native": "https://github.com/expo/react-native/archive/sdk-40.0.1.tar.gz",
    "react-native-dotenv": "^2.5.3",
    "react-native-gesture-handler": "~1.8.0",
    "react-native-safe-area-context": "3.1.9",
    "react-native-screens": "~2.15.0",
    "react-native-web": "~0.13.12",
    "react-native-webview": "^11.3.1",
    "styled-components": "^5.2.1"
  },
  "devDependencies": {
    "@babel/core": "~7.9.0",
    "@commitlint/config-conventional": "^9.0.1",
    "@storybook/addon-a11y": "^6.1.21",
    "@storybook/addon-actions": "^5.3",
    "@storybook/addon-knobs": "^5.3",
    "@storybook/addon-links": "^5.3",
    "@storybook/addon-ondevice-actions": "^5.3.23",
    "@storybook/addon-ondevice-knobs": "^5.3.25",
    "@storybook/react-native": "^5.3.25",
    "@storybook/react-native-server": "^5.3.23",
    "@testing-library/react-native": "^7.2.0",
    "@types/jest": "^26.0.21",
    "@types/react": "~16.9.35",
    "@types/react-native": "~0.63.2",
    "@types/react-test-renderer": "^17.0.1",
    "@types/styled-components": "^5.1.9",
    "@types/styled-components-react-native": "^5.1.1",
    "@typescript-eslint/eslint-plugin": "^3.4.0",
    "@typescript-eslint/parser": "^3.4.0",
    "babel-loader": "^8.2.2",
    "eslint": "^6.6.0",
    "eslint-config-prettier": "^6.11.0",
    "eslint-plugin-better-styled-components": "^1.1.2",
    "eslint-plugin-import": "^2.22.0",
    "eslint-plugin-prettier": "^3.1.4",
    "eslint-plugin-react": "^7.23.1",
    "eslint-plugin-react-hooks": "^4.0.6",
    "eslint-plugin-react-native": "^3.10.0",
    "eslint-plugin-sort-destructure-keys": "^1.3.5",
    "eslint-plugin-typescript-sort-keys": "^1.2.0",
    "husky": "^4.2.5",
    "jest-expo": "~40.0.0",
    "lint-staged": "^10.2.11",
    "prettier": "^2.0.5",
    "react-native-storybook-loader": "^2.0.2",
    "react-test-renderer": "^17.0.2",
    "typescript": "~4.0.0"
  },
  "private": true,
  "commitlint": {
    "extends": [
      "@commitlint/config-conventional"
    ]
  },
  "husky": {
    "hooks": {
      "pre-commit": "lint-staged",
      "commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
    }
  },
  "lint-staged": {
    "src/**/*.{js,jsx,ts,tsx}": [
      "eslint --config .eslintrc.json --ignore-path .eslintignore --fix",
      "prettier --write --config .prettierrc.json --ignore-path .prettierignore",
      "git add"
    ]
  },
  "config": {
    "react-native-storybook-loader": {
      "searchDir": [
        "./src/components"
      ],
      "pattern": "**/__stories__/*.story.tsx",
      "outputFile": "./src/storybook/storyLoader.js"
    }
  }
}

.eslintrc.json

{
  "env": {
    "browser": true,
    "react-native/react-native": true,
    "commonjs": true,
    "node": true,
    "es6": true
  },
  "extends": [
    "plugin:react/recommended",
    "plugin:@typescript-eslint/recommended",
    "plugin:import/typescript",
    "plugin:prettier/recommended",
    "prettier/@typescript-eslint"
  ],
  "parser": "@typescript-eslint/parser",
  "parserOptions": {
    "ecmaFeatures": {
      "jsx": true
    },
    "ecmaVersion": 2020,
    "project": ["./tsconfig.json"],
    "sourceType": "module"
  },
  "plugins": [
    "@typescript-eslint",
    "better-styled-components",
    "import",
    "prettier",
    "react",
    "react-hooks",
    "react-native",
    "sort-destructure-keys",
    "typescript-sort-keys"
  ],
  "rules": {
// Bunch of rules that I won't add

Using node v14.16.0

manuelxaguilar avatar Mar 26 '21 18:03 manuelxaguilar

Have the same issue with "eslint-plugin-react-native": "^3.10.0", when trying to replace

<SomeComponent prop={array.reduce((acc, item) => [...acc, processItem(item)], [])} />

with

const prop = useMemo(
    () => 
        array.reduce(
            (acc, item) => [
                ...acc, 
                processItem(item)
            ],
            []
        ), 
    [array]
);

// ...

<SomeComponent prop={prop} />

Disabled this rule for now, waiting for a proper solution.

eqlion avatar Jun 03 '21 14:06 eqlion

This is still present in 3.11.0.

fnimick avatar Jun 18 '21 19:06 fnimick

The minimum conditions to reproduce this linting crash are: => Having a component with a function passed as a prop AND any kind of children.

So, the minimal reproducible example is the following one:

<MyComponent myFunctionProp={() => {}}>my children</MyComponent>;

To fix this issue, you should define the prop before passing it, like so:

const myFunction = () => {};
<MyComponent myFunctionProp={myFunction}>my children</MyComponent>;

VincentJouanne avatar Aug 12 '21 16:08 VincentJouanne

To fix this issue, you should define the prop before passing it, like so:

@VincentJouanne This doesn't work with useCallback hook though :slightly_frowning_face:

GrabbenD avatar Aug 12 '21 17:08 GrabbenD

@xRiot Can you post the minimum reproducible example with a useCallback() ?

VincentJouanne avatar Aug 12 '21 19:08 VincentJouanne

Still getting this issue on:

eslint 7.14.0 eslint-plugin-react-native: 3.11.0

:/

bombillazo avatar Oct 20 '21 02:10 bombillazo

Really appreciate the amount of attention this gets from the maintainers.

npavlovichero avatar Nov 05 '21 13:11 npavlovichero

The minimum conditions to reproduce this linting crash are: => Having a component with a function passed as a prop AND any kind of children.

So, the minimal reproducible example is the following one:

<MyComponent myFunctionProp={() => {}}>my children</MyComponent>;

To fix this issue, you should define the prop before passing it, like so:

const myFunction = () => {};
<MyComponent myFunctionProp={myFunction}>my children</MyComponent>;

no help if I need to pass an arg, sadly

willjenks avatar Dec 10 '21 15:12 willjenks

The minimum conditions to reproduce this linting crash are: => Having a component with a function passed as a prop AND any kind of children. So, the minimal reproducible example is the following one: <MyComponent myFunctionProp={() => {}}>my children</MyComponent>; To fix this issue, you should define the prop before passing it, like so:

const myFunction = () => {};
<MyComponent myFunctionProp={myFunction}>my children</MyComponent>;

no help if I need to pass an arg, sadly

what do you mean by that?

npavlovichero avatar Dec 10 '21 15:12 npavlovichero

The minimum conditions to reproduce this linting crash are: => Having a component with a function passed as a prop AND any kind of children. So, the minimal reproducible example is the following one: <MyComponent myFunctionProp={() => {}}>my children</MyComponent>; To fix this issue, you should define the prop before passing it, like so:

const myFunction = () => {};
<MyComponent myFunctionProp={myFunction}>my children</MyComponent>;

no help if I need to pass an arg, sadly

what do you mean by that?

const onPressButton = id => foo(id)

....

{ myButtons.map((text,id)=><Button onPress={()=>onPressButton(id)}>{text}</Button>) }


ETA: I have worked out a work-around for this - a curried function:

const onPressButton = id => () => foo(id)     <--- notice extra () =>

....

{ myButtons.map((text,id)=><Button onPress={onPressButton(id)}>{text}</Button>) }


willjenks avatar Dec 10 '21 16:12 willjenks

I had this problem with the code below

 <Text>
    Something?{' '}
    <TouchableOpacity
      onPress={() => fun()}
    >
      <Text>
        Something
      </Text>
    </TouchableOpacity>
</Text>

I have no idea why, I just tweaked the text to this and the error went away.

 <Text>
    <Text>Something? </Text>
    <TouchableOpacity
      onPress={() => fun()}
    >
      <Text>
        Something
      </Text>
    </TouchableOpacity>
</Text>

Might be related to some structure of nested text RN elements in my case.

zemuldo avatar Jan 21 '22 06:01 zemuldo

#314 should fix this

hsource avatar Apr 21 '22 22:04 hsource

@hsource still exists

gabimoncha avatar May 02 '22 14:05 gabimoncha

@hsource still exists

That shouldn't be right! What error message are you seeing? If you'd like to test with a build, you can also do yarn add hsource/eslint-plugin-react-native#v4.0.0-wanderlog.2 to use the patched version

hsource avatar May 03 '22 16:05 hsource

Thanks! I'll try it out. Basically the linter doesn't detect a custom component

gabimoncha avatar May 03 '22 17:05 gabimoncha

For those interested, here is my brief explanation about this issue: https://github.com/Intellicode/eslint-plugin-react-native/pull/314#issuecomment-1156553355

JLHwung avatar Jun 15 '22 14:06 JLHwung

When will this fix be released @hsource @JLHwung ?

thongquach-eh avatar Jun 20 '22 04:06 thongquach-eh

The problem still exists in v4.0.0. Have to temporarily turn the rule off

xsjcTony avatar Sep 23 '22 00:09 xsjcTony

Had the same problem, fixed it by assigning the value to a constant. Simplified example:

Didn't work: function displaySomething() { return ( <Text>functionThatReturnsAName(id)</Text> )}

Works:

function displaySomething() { const name = functionThatReturnsAName(id) return ( <Text>{name}</Text> )}

Not sure if this is helpful for anyone but worked for me and it is prettier imo.

Magnus-V avatar Oct 06 '22 10:10 Magnus-V

Any timeline on the possibility of the PR that fixes it being merged?

vincent-paing avatar Jan 04 '23 07:01 vincent-paing

Still present in!

eslint: 8.35.0 eslint-plugin-react: 7.32.2 eslint-plugin-react-native: 4.0.0

Gxmadix avatar Feb 28 '23 10:02 Gxmadix

Having this issue as well...

My config:

[email protected]
[email protected]
[email protected]

The error:

$ eslint .

Oops! Something went wrong! :(

ESLint: 8.44.0

Error: Couldn't find a Program
Occurred while linting /home/vibia/platform/services/app-on-site/apps/expo/app/paper/paper.tsx:62
Rule: "react-native/no-raw-text"
    at Scope.getProgramParent (/home/vibia/platform/services/app-on-site/node_modules/eslint-plugin-react-native/node_modules/@babel/traverse/lib/scope/index.js:753:11)
    at Scope.crawl (/home/vibia/platform/services/app-on-site/node_modules/eslint-plugin-react-native/node_modules/@babel/traverse/lib/scope/index.js:665:32)
    at Scope.init (/home/vibia/platform/services/app-on-site/node_modules/eslint-plugin-react-native/node_modules/@babel/traverse/lib/scope/index.js:655:12)
    at NodePath.setScope (/home/vibia/platform/services/app-on-site/node_modules/eslint-plugin-react-native/node_modules/@babel/traverse/lib/path/context.js:120:61)
    at NodePath.setContext (/home/vibia/platform/services/app-on-site/node_modules/eslint-plugin-react-native/node_modules/@babel/traverse/lib/path/context.js:132:8)
    at NodePath.pushContext (/home/vibia/platform/services/app-on-site/node_modules/eslint-plugin-react-native/node_modules/@babel/traverse/lib/path/context.js:189:8)
    at TraversalContext.visitQueue (/home/vibia/platform/services/app-on-site/node_modules/eslint-plugin-react-native/node_modules/@babel/traverse/lib/context.js:78:14)
    at TraversalContext.visitSingle (/home/vibia/platform/services/app-on-site/node_modules/eslint-plugin-react-native/node_modules/@babel/traverse/lib/context.js:65:19)
    at TraversalContext.visit (/home/vibia/platform/services/app-on-site/node_modules/eslint-plugin-react-native/node_modules/@babel/traverse/lib/context.js:109:19)
    at traverseNode (/home/vibia/platform/services/app-on-site/node_modules/eslint-plugin-react-native/node_modules/@babel/traverse/lib/traverse-node.js:18:17)
error Command failed with exit code 2.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
error Command failed.
Exit code: 2

mtzfactory avatar Jul 06 '23 09:07 mtzfactory