Skip to content

linter: react-perf/jsx-no-new-object-as-prop not seeing through satisfies or as typescript statement #13717

@pcorpet

Description

@pcorpet

What version of Oxlint are you using?

1.12.0

What command did you run?

oxlint

What does your .oxlintrc.json config file look like?

{
  "categories": {
    "correctness": "error",
    "pedantic": "error",
    "perf": "error",
    "restriction": "error",
    "suspicious": "error"
  },
  "ignorePatterns": ["**/node_modules/**", "**/.yarn/**", "**/*.cjs", "**/*.js", "src/api-client/**"],
  "plugins": ["import", "jsx-a11y", "oxc", "promise", "react", "react-perf", "typescript", "unicorn", "vitest"],
  "rules": {
    "max-dependencies": "off",
    "max-lines": "off",
    "max-lines-per-function": "off",
    "symbol-description": "off",
    "eslint/no-alert": "off",
    "eslint/no-bitwise": "off",
    "import/extensions": "off",
    "import/unambiguous": "off",
    "oxc/no-barrel-file": "off",
    "oxc/no-accumulating-spread": "off",
    "promise/catch-or-return": "off",
    "react/iframe-missing-sandbox": "off",
    "react/no-array-index-key": "off",
    "react-perf/jsx-no-jsx-as-prop": "off",
    "typescript/ban-types": "off",
    "unicorn/no-array-reduce": "off",
    "unicorn/no-negation-in-equality-check": "off",
    "unicorn/no-useless-promise-resolve-reject": "off",
    "vitest/expect-expect": "off",
    "vitest/no-conditional-expect": "off",
    "vitest/no-conditional-in-test": "off",
    "vitest/no-disabled-tests": "off",
    "vitest/no-standalone-expect": "off",
    "no-negated-condition": "off",
    "eslint/no-undefined": "off",
    "eslint/no-void": "off",
    "import/no-default-export": "off",
    "oxc/no-async-await": "off",
    "oxc/no-optional-chaining": "off",
    "oxc/no-rest-spread-properties": "off",
    "react/jsx-filename-extension": ["error", { "extensions": [".tsx"] }],
    "react/react-in-jsx-scope": "off",
    "typescript/explicit-function-return-type": "off",
    "typescript/explicit-module-boundary-types": "off",
    "unicorn/no-nested-ternary": "off",
    "unicorn/no-useless-undefined": "off",
    "unicorn/prefer-query-selector": "off",
    "react-perf/jsx-no-new-array-as-prop": "error",
    "react-perf/jsx-no-new-function-as-prop": "error",
    "react-perf/jsx-no-new-object-as-prop": "error",
    "vitest/valid-expect": ["error", { "maxArgs": 2 }]
  }
}

What happened?

Consider the four snippets below of react code:

  1. Using type annotation for style
const MyComponent = () => {
	const [hidden, setHidden] = useState(false)
	const onClick = useCallback(() => setHidden(true), [])
	const style: CSSProperties = {
		visibility: hidden ? 'hidden' : 'visible',
	}
	return <button style={style} onClick={onClick} type="submit" />
}
  1. Using as cast for style
const MyComponent = () => {
	const [hidden, setHidden] = useState(false)
	const onClick = useCallback(() => setHidden(true), [])
	const style = {
		visibility: hidden ? 'hidden' : 'visible',
	} as CSSProperties
	return <button style={style} onClick={onClick} type="submit" />
}
  1. Using as const assertion for style
const MyComponent = () => {
	const [hidden, setHidden] = useState(false)
	const onClick = useCallback(() => setHidden(true), [])
	const style = {
		visibility: hidden ? 'hidden' : 'visible',
	} as const
	return <button style={style} onClick={onClick} type="submit" />
}
  1. Using satisfies type assertion for style
const MyComponent = () => {
	const [hidden, setHidden] = useState(false)
	const onClick = useCallback(() => setHidden(true), [])
	const style = {
		visibility: hidden ? 'hidden' : 'visible',
	} satisfies CSSProperties
	return <button style={style} onClick={onClick} type="submit" />
}

Only the first one would raise the error
eslint-plugin-react-perf(jsx-no-new-object-as-prop): JSX attribute values should not contain objects created in the same scope.

However at runtime, they all would create a new style object at each render, so oxlint should raise an issue on all 4 of them.

Metadata

Metadata

Assignees

Labels

Type

Priority

None yet

Effort

None yet

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions