Skip to content

Commit

Permalink
avoid useMemo with empty array [] since React can't guarantee sta…
Browse files Browse the repository at this point in the history
…ble reference, + lint restrict syntax for future mistakes (#3063)

* avoid `useMemo` with empty array `[]` since React can't guarantee stable reference, + lint restrict syntax for future mistakes

* fix migration

* prettify
  • Loading branch information
dimaMachina authored Mar 5, 2023
1 parent 392e193 commit 5792aaa
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 70 deletions.
6 changes: 6 additions & 0 deletions .changeset/two-icons-rhyme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@graphiql/plugin-code-exporter': patch
'@graphiql/plugin-explorer': patch
---

avoid `useMemo` with empty array `[]` since React can't guarantee stable reference, + lint restrict syntax for future mistakes
11 changes: 10 additions & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,16 @@ module.exports = {
'no-nested-ternary': 0,
'no-new-object': 1,
'no-plusplus': 0,
'no-restricted-syntax': 0,
'no-restricted-syntax': [
'error',
{
// ❌ useMemo(…, [])
selector:
'CallExpression[callee.name=useMemo][arguments.1.type=ArrayExpression][arguments.1.elements.length=0]',
message:
"`useMemo` with an empty dependency array can't provide a stable reference, use `useRef` instead.",
},
],
'no-ternary': 0,
'no-underscore-dangle': 0,
'no-unneeded-ternary': 0,
Expand Down
22 changes: 11 additions & 11 deletions docs/migration/graphiql-2.0.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ been removed and where you can find them now:
The `GraphiQL` component in `graphiql@1.x` was a class component. That allowed
easy access to its props, state and methods by attaching a ref to it like so:

```jsx
```tsx
import { createGraphiQLFetcher } from '@graphiql/toolkit';
import { GraphiQL } from 'graphiql';
import React from 'react';
Expand Down Expand Up @@ -228,16 +228,16 @@ components that can be passed as children to the `GraphiQL` components and
override certain parts of the UI:

- `GraphiQL.Logo`: Overrides the "logo" at the top right of the screen. By
default it contains the text "Graph*i*QL".
- `GraphiQL.Toolbar`: Overrides the toolbar next to the query editor. By default
if contains buttons for prettifying the current editor contents, merging
fragment definitions into the operation definition and copying the contents of
the query editor to the clipboard. Note that the default buttons will not be
shown when passing this component as child to `GraphiQL`, instead it will show
the children you pass to `GraphiQL.Toolbar`. The execute button will always be
shown. If you want to keep the default buttons and add additional buttons you
can use the `toolbar` prop.
- `GraphiQL.Footer`: Adds a section below the response editor. By default this
default, it contains the text "Graph*i*QL".
- `GraphiQL.Toolbar`: Overrides the toolbar next to the query editor. By
default, if contains buttons for prettifying the current editor contents,
merging fragment definitions into the operation definition and copying the
contents of the query editor to the clipboard. Note that the default buttons
will not be shown when passing this component as child to `GraphiQL`, instead
it will show the children you pass to `GraphiQL.Toolbar`. The execute button
will always be shown. If you want to keep the default buttons and add
additional buttons you can use the `toolbar` prop.
- `GraphiQL.Footer`: Adds a section below the response editor. By default, this
won't show up in the UI.

Here is a list of all the static properties that have been removed and their
Expand Down
52 changes: 25 additions & 27 deletions packages/graphiql-plugin-code-exporter/src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { GraphiQLPlugin } from '@graphiql/react';
import { useMemo, useRef } from 'react';
import { useRef } from 'react';
import GraphiQLCodeExporter, {
GraphiQLCodeExporterProps,
} from 'graphiql-code-exporter';
Expand All @@ -10,31 +10,29 @@ import './index.css';
export function useExporterPlugin(props: GraphiQLCodeExporterProps) {
const propsRef = useRef(props);
propsRef.current = props;
return useMemo<GraphiQLPlugin>(
() => ({
title: 'GraphiQL Code Exporter',
icon: () => (
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
strokeWidth={1.5}
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M9 8.25H7.5a2.25 2.25 0 00-2.25 2.25v9a2.25 2.25 0 002.25 2.25h9a2.25 2.25 0 002.25-2.25v-9a2.25 2.25 0 00-2.25-2.25H15m0-3l-3-3m0 0l-3 3m3-3V15"
/>
</svg>
),
content: () => (
<GraphiQLCodeExporter
codeMirrorTheme="graphiql"
{...propsRef.current}

const pluginRef = useRef<GraphiQLPlugin>();
pluginRef.current ||= {
title: 'GraphiQL Code Exporter',
icon: () => (
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
strokeWidth="1.5"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M9 8.25H7.5a2.25 2.25 0 00-2.25 2.25v9a2.25 2.25 0 002.25 2.25h9a2.25 2.25 0 002.25-2.25v-9a2.25 2.25 0 00-2.25-2.25H15m0-3l-3-3m0 0l-3 3m3-3V15"
/>
),
}),
[],
);
</svg>
),
content: () => (
<GraphiQLCodeExporter codeMirrorTheme="graphiql" {...propsRef.current} />
),
};

return pluginRef.current;
}
60 changes: 30 additions & 30 deletions packages/graphiql-plugin-explorer/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
useSchemaContext,
} from '@graphiql/react';
import GraphiQLExplorer, { GraphiQLExplorerProps } from 'graphiql-explorer';
import { useMemo, useRef } from 'react';
import { useRef } from 'react';

import './graphiql-explorer.d.ts';
import './index.css';
Expand Down Expand Up @@ -129,33 +129,33 @@ function ExplorerPlugin(props: GraphiQLExplorerProps) {
export function useExplorerPlugin(props: GraphiQLExplorerProps) {
const propsRef = useRef(props);
propsRef.current = props;
return useMemo<GraphiQLPlugin>(
() => ({
title: 'GraphiQL Explorer',
icon: () => (
<svg height="1em" strokeWidth="1.5" viewBox="0 0 24 24" fill="none">
<path
d="M18 6H20M22 6H20M20 6V4M20 6V8"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M21.4 20H2.6C2.26863 20 2 19.7314 2 19.4V11H21.4C21.7314 11 22 11.2686 22 11.6V19.4C22 19.7314 21.7314 20 21.4 20Z"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M2 11V4.6C2 4.26863 2.26863 4 2.6 4H8.77805C8.92127 4 9.05977 4.05124 9.16852 4.14445L12.3315 6.85555C12.4402 6.94876 12.5787 7 12.722 7H14"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
),
content: () => <ExplorerPlugin {...propsRef.current} />,
}),
[],
);

const pluginRef = useRef<GraphiQLPlugin>();
pluginRef.current ||= {
title: 'GraphiQL Explorer',
icon: () => (
<svg height="1em" strokeWidth="1.5" viewBox="0 0 24 24" fill="none">
<path
d="M18 6H20M22 6H20M20 6V4M20 6V8"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M21.4 20H2.6C2.26863 20 2 19.7314 2 19.4V11H21.4C21.7314 11 22 11.2686 22 11.6V19.4C22 19.7314 21.7314 20 21.4 20Z"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M2 11V4.6C2 4.26863 2.26863 4 2.6 4H8.77805C8.92127 4 9.05977 4.05124 9.16852 4.14445L12.3315 6.85555C12.4402 6.94876 12.5787 7 12.722 7H14"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
),
content: () => <ExplorerPlugin {...propsRef.current} />,
};
return pluginRef.current;
}
5 changes: 4 additions & 1 deletion packages/graphiql/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,10 @@ import 'graphiql/graphiql.css';

const fetcher = createGraphiQLFetcher({ url: 'https://my.backend/graphql' });

ReactDOM.render(<GraphiQL fetcher={fetcher} />, document.getElementById('root'));
ReactDOM.render(
<GraphiQL fetcher={fetcher} />,
document.getElementById('root'),
);
```

### Using as UMD bundle over CDN (Unpkg, JSDelivr, etc)
Expand Down

0 comments on commit 5792aaa

Please sign in to comment.