Repository: pmndrs/zustand
Pull request #531 (2021-08-14 03:59:47)

chore: update eslintrc and use react-jsx
follow https://github.com/pmndrs/jotai/pull/656
and use react-jsx now.

codesandbox[bot]: This pull request is automatically built and testable in [CodeSandbox](https://codesandbox.io).

  To see build info of the built libraries, click [here](https://ci.codesandbox.io/status/pmndrs/zustand/pr/531/builds/159577) or the icon next to each commit SHA.

Latest deployment of this branch, based on commit b18936a5e967f72c9efcacdc86b60d28621c8386:

|Sandbox| Source |
|--|--|
|[React](https://codesandbox.io/s/react-mw8z1)| Configuration |
|[React Typescript](https://codesandbox.io/s/react-typescript-fx4gx)| Configuration |
|[React Browserify](https://codesandbox.io/s/react-browserify-qpo1l)| Configuration |
|[React Snowpack](https://codesandbox.io/s/react-snowpack-4ynxh)| Configuration |
|[React Parcel](https://codesandbox.io/s/react-parcel-tnhxe)| Configuration |


Patch:
diff --git a/.eslintrc.json b/.eslintrc.json
index e6e8a1e..6b18840 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -12,34 +12,74 @@
     "plugin:import/errors",
     "plugin:import/warnings"
   ],
-  "plugins": ["@typescript-eslint", "react", "prettier", "react-hooks", "import", "jest"],
+  "plugins": [
+    "@typescript-eslint",
+    "react",
+    "prettier",
+    "react-hooks",
+    "import",
+    "jest"
+  ],
   "parser": "@typescript-eslint/parser",
   "parserOptions": {
     "ecmaVersion": 2018,
     "sourceType": "module",
     "ecmaFeatures": {
       "jsx": true
-    },
-    "rules": {
-      "curly": ["warn", "multi-line", "consistent"],
-      "no-console": "off",
-      "no-empty-pattern": "warn",
-      "no-duplicate-imports": "error",
-      "import/no-unresolved": ["error", { "commonjs": true, "amd": true }],
-      "import/export": "error",
-      "import/named": "off",
-      "import/namespace": "off",
-      "import/default": "off",
-      "@typescript-eslint/explicit-module-boundary-types": "off",
-      "no-unused-vars": ["warn", { "argsIgnorePattern": "^_", "varsIgnorePattern": "^_" }],
-      "@typescript-eslint/no-unused-vars": ["warn", { "argsIgnorePattern": "^_", "varsIgnorePattern": "^_" }],
-      "@typescript-eslint/no-use-before-define": "off",
-      "@typescript-eslint/no-empty-function": "off",
-      "@typescript-eslint/no-empty-interface": "off",
-      "@typescript-eslint/no-explicit-any": "off",
-      "jest/consistent-test-it": ["error", { "fn": "it", "withinDescribe": "it" }]
     }
   },
+  "rules": {
+    "curly": ["warn", "multi-line", "consistent"],
+    "no-console": "off",
+    "import/no-unresolved": ["error", { "commonjs": true, "amd": true }],
+    "import/export": "error",
+    "@typescript-eslint/no-duplicate-imports": ["error"],
+    "@typescript-eslint/explicit-module-boundary-types": "off",
+    "@typescript-eslint/no-unused-vars": [
+      "warn",
+      { "argsIgnorePattern": "^_", "varsIgnorePattern": "^_" }
+    ],
+    "@typescript-eslint/no-use-before-define": "off",
+    "@typescript-eslint/no-empty-function": "off",
+    "@typescript-eslint/no-empty-interface": "off",
+    "@typescript-eslint/no-explicit-any": "off",
+    "jest/consistent-test-it": [
+      "error",
+      { "fn": "it", "withinDescribe": "it" }
+    ],
+    "import/order": [
+      "error",
+      {
+        "alphabetize": { "order": "asc", "caseInsensitive": true },
+        "groups": [
+          "builtin",
+          "external",
+          "internal",
+          "parent",
+          "sibling",
+          "index",
+          "object"
+        ],
+        "newlines-between": "never",
+        "pathGroups": [
+          {
+            "pattern": "react",
+            "group": "builtin",
+            "position": "before"
+          }
+        ],
+        "pathGroupsExcludedImportTypes": ["builtin"]
+      }
+    ],
+    "react/jsx-uses-react": "off",
+    "react/react-in-jsx-scope": "off",
+    "sort-imports": [
+      "error",
+      {
+        "ignoreDeclarationSort": true
+      }
+    ]
+  },
   "settings": {
     "react": {
       "version": "detect"
diff --git a/babel.config.js b/babel.config.js
index b5c3ace..fa15c8a 100644
--- a/babel.config.js
+++ b/babel.config.js
@@ -16,7 +16,12 @@ module.exports = (api, targets) => {
       ],
     ],
     plugins: [
-      '@babel/plugin-transform-react-jsx',
+      [
+        '@babel/plugin-transform-react-jsx',
+        {
+          runtime: 'automatic',
+        },
+      ],
       ['@babel/plugin-transform-typescript', { isTSX: true }],
     ],
   }
diff --git a/src/index.ts b/src/index.ts
index 45a77c0..ad9ef62 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -7,8 +7,8 @@ import createImpl, {
   State,
   StateCreator,
   StateSelector,
-  Subscribe,
   StoreApi,
+  Subscribe,
 } from './vanilla'
 export * from './vanilla'
 
diff --git a/tsconfig.json b/tsconfig.json
index 83b23d7..5db95f4 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -2,7 +2,7 @@
   "compilerOptions": {
     "target": "esnext",
     "strict": true,
-    "jsx": "preserve",
+    "jsx": "react-jsx",
     "allowSyntheticDefaultImports": true,
     "esModuleInterop": true,
     "moduleResolution": "node",


Test patch:
diff --git a/tests/basic.test.tsx b/tests/basic.test.tsx
index 7ffa3d1..aaab3e4 100644
--- a/tests/basic.test.tsx
+++ b/tests/basic.test.tsx
@@ -1,7 +1,12 @@
-import React from 'react'
-import ReactDOM from 'react-dom'
+import {
+  Component as ClassComponent,
+  useEffect,
+  useLayoutEffect,
+  useState,
+} from 'react'
 import { act, fireEvent, render } from '@testing-library/react'
-import create, { StateSelector, EqualityChecker, SetState } from '../src/index'
+import ReactDOM from 'react-dom'
+import create, { EqualityChecker, SetState, StateSelector } from '../src/index'
 
 it('creates a store hook and api object', () => {
   let params
@@ -39,7 +44,7 @@ it('uses the store with no args', async () => {
 
   function Counter() {
     const { count, inc } = useStore()
-    React.useEffect(inc, [inc])
+    useEffect(inc, [inc])
     return <div>count: {count}</div>
   }
 
@@ -57,7 +62,7 @@ it('uses the store with selectors', async () => {
   function Counter() {
     const count = useStore((s) => s.count)
     const inc = useStore((s) => s.inc)
-    React.useEffect(inc, [inc])
+    useEffect(inc, [inc])
     return <div>count: {count}</div>
   }
 
@@ -137,7 +142,7 @@ it('re-renders with useLayoutEffect', async () => {
 
   function Component() {
     const { state } = useStore()
-    React.useLayoutEffect(() => {
+    useLayoutEffect(() => {
       useStore.setState({ state: true })
     }, [])
     return <>{`${state}`}</>
@@ -157,7 +162,7 @@ it('can batch updates', async () => {
 
   function Counter() {
     const { count, inc } = useStore()
-    React.useEffect(() => {
+    useEffect(() => {
       ReactDOM.unstable_batchedUpdates(() => {
         inc()
         inc()
@@ -279,7 +284,7 @@ it('can throw an error in selector', async () => {
     // @ts-expect-error This function is supposed to throw an error
     s.value.toUpperCase()
 
-  class ErrorBoundary extends React.Component<{}, { hasError: boolean }> {
+  class ErrorBoundary extends ClassComponent<{}, { hasError: boolean }> {
     constructor(props: {}) {
       super(props)
       this.state = { hasError: false }
@@ -323,7 +328,7 @@ it('can throw an error in equality checker', async () => {
     // @ts-expect-error This function is supposed to throw an error
     a.value.trim() === b.value?.trim()
 
-  class ErrorBoundary extends React.Component<{}, { hasError: boolean }> {
+  class ErrorBoundary extends ClassComponent<{}, { hasError: boolean }> {
     constructor(props: {}) {
       super(props)
       this.state = { hasError: false }
@@ -514,15 +519,13 @@ it('ensures the correct subscriber is removed on unmount', async () => {
   }
 
   function CountWithInitialIncrement() {
-    React.useLayoutEffect(increment, [])
+    useLayoutEffect(increment, [])
     return <Count />
   }
 
   function Component() {
-    const [Counter, setCounter] = React.useState(
-      () => CountWithInitialIncrement
-    )
-    React.useLayoutEffect(() => {
+    const [Counter, setCounter] = useState(() => CountWithInitialIncrement)
+    useLayoutEffect(() => {
       setCounter(() => Count)
     }, [])
     return (
diff --git a/tests/context.test.tsx b/tests/context.test.tsx
index bc33450..af62be2 100644
--- a/tests/context.test.tsx
+++ b/tests/context.test.tsx
@@ -1,7 +1,7 @@
-import React from 'react'
+import { Component as ClassComponent, useEffect, useState } from 'react'
 import { render } from '@testing-library/react'
-import create from '../src/index'
 import createContext from '../src/context'
+import create from '../src/index'
 
 type CounterState = {
   count: number
@@ -19,7 +19,7 @@ it('creates and uses context store', async () => {
 
   function Counter() {
     const { count, inc } = useStore()
-    React.useEffect(inc, [inc])
+    useEffect(inc, [inc])
     return <div>count: {count * 1}</div>
   }
 
@@ -44,7 +44,7 @@ it('uses context store with selectors', async () => {
   function Counter() {
     const count = useStore((state) => state.count)
     const inc = useStore((state) => state.inc)
-    React.useEffect(inc, [inc])
+    useEffect(inc, [inc])
     return <div>count: {count * 1}</div>
   }
 
@@ -68,8 +68,8 @@ it('uses context store api', async () => {
 
   function Counter() {
     const storeApi = useStoreApi()
-    const [count, setCount] = React.useState(0)
-    React.useEffect(
+    const [count, setCount] = useState(0)
+    useEffect(
       () =>
         storeApi.subscribe(
           () => setCount(storeApi.getState().count),
@@ -77,10 +77,10 @@ it('uses context store api', async () => {
         ),
       [storeApi]
     )
-    React.useEffect(() => {
+    useEffect(() => {
       storeApi.setState({ count: storeApi.getState().count + 1 })
     }, [storeApi])
-    React.useEffect(() => {
+    useEffect(() => {
       if (count === 1) {
         storeApi.destroy()
         storeApi.setState({ count: storeApi.getState().count + 1 })
@@ -101,7 +101,7 @@ it('uses context store api', async () => {
 it('throws error when not using provider', async () => {
   console.error = jest.fn()
 
-  class ErrorBoundary extends React.Component<{}, { hasError: boolean }> {
+  class ErrorBoundary extends ClassComponent<{}, { hasError: boolean }> {
     constructor(props: {}) {
       super(props)
       this.state = { hasError: false }
diff --git a/tests/middlewareTypes.test.tsx b/tests/middlewareTypes.test.tsx
index cd3cf19..264a845 100644
--- a/tests/middlewareTypes.test.tsx
+++ b/tests/middlewareTypes.test.tsx
@@ -1,8 +1,8 @@
 import { produce } from 'immer'
 import type { Draft } from 'immer'
 import create, { UseStore } from '../src'
+import { NamedSet, devtools, persist } from '../src/middleware'
 import { State, StateCreator } from '../src/vanilla'
-import { devtools, NamedSet, persist } from '../src/middleware'
 
 type TImmerConfigFn<T extends State> = (fn: (draft: Draft<T>) => void) => void
 type TImmerConfig<T extends State> = StateCreator<T, TImmerConfigFn<T>>
@@ -66,6 +66,7 @@ it('should have correct type when creating store with devtool', () => {
 
     return <></>
   }
+  TestComponent
 })
 
 it('should have correct type when creating store with devtool and immer', () => {
@@ -94,6 +95,7 @@ it('should have correct type when creating store with devtool and immer', () =>
 
     return <></>
   }
+  TestComponent
 })
 
 it('should have correct type when creating store with devtool and persist', () => {
@@ -126,6 +128,7 @@ it('should have correct type when creating store with devtool and persist', () =
 
     return <></>
   }
+  TestComponent
 })
 
 it('should have correct type when creating store without middleware', () => {
@@ -144,6 +147,7 @@ it('should have correct type when creating store without middleware', () => {
 
     return <></>
   }
+  TestComponent
 })
 
 it('should have correct type when creating store with persist', () => {
@@ -174,6 +178,7 @@ it('should have correct type when creating store with persist', () => {
 
     return <></>
   }
+  TestComponent
 })
 
 it('should have correct type when creating store with immer', () => {
@@ -198,6 +203,7 @@ it('should have correct type when creating store with immer', () => {
 
     return <></>
   }
+  TestComponent
 })
 
 it('should have correct type when creating store with devtool, persist and immer', () => {
@@ -231,4 +237,5 @@ it('should have correct type when creating store with devtool, persist and immer
 
     return <></>
   }
+  TestComponent
 })
diff --git a/tests/persistAsync.test.tsx b/tests/persistAsync.test.tsx
index a164e27..458535d 100644
--- a/tests/persistAsync.test.tsx
+++ b/tests/persistAsync.test.tsx
@@ -1,5 +1,4 @@
-import React from 'react'
-import { act, cleanup, render } from '@testing-library/react'
+import { act, render } from '@testing-library/react'
 import create from '../src/index'
 import { persist } from '../src/middleware'
 
@@ -211,7 +210,7 @@ describe('persist middleware with async configuration', () => {
           state: { count: 42 },
           version: 12,
         }),
-      setItem: (_: string, value: string) => {},
+      setItem: (_: string, _value: string) => {},
     }
 
     const useStore = create(
diff --git a/tests/persistSync.test.tsx b/tests/persistSync.test.tsx
index e146d0f..62ff134 100644
--- a/tests/persistSync.test.tsx
+++ b/tests/persistSync.test.tsx
@@ -164,7 +164,7 @@ describe('persist middleware with sync configuration', () => {
           state: { count: 42 },
           version: 12,
         }),
-      setItem: (_: string, value: string) => {},
+      setItem: (_: string, _value: string) => {},
     }
 
     const useStore = create(
diff --git a/tests/types.test.tsx b/tests/types.test.tsx
index 171c6b0..0aad4e4 100644
--- a/tests/types.test.tsx
+++ b/tests/types.test.tsx
@@ -1,16 +1,16 @@
 import create, {
+  Destroy,
+  EqualityChecker,
+  GetState,
+  PartialState,
+  SetState,
   State,
+  StateCreator,
   StateListener,
   StateSelector,
-  PartialState,
-  EqualityChecker,
-  StateCreator,
-  SetState,
-  GetState,
+  StoreApi,
   Subscribe,
-  Destroy,
   UseStore,
-  StoreApi,
 } from '../src/index'
 
 it('can use exposed types', () => {