Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[1/2] [@graphiql/react] compile source code with react-compiler, remove useMemo and useCallback usages #3821

Merged
merged 33 commits into from
Dec 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
f590ae4
aa
dimaMachina Dec 11, 2024
810b0b2
aa
dimaMachina Dec 11, 2024
8066724
aa
dimaMachina Dec 11, 2024
4039e39
aa
dimaMachina Dec 11, 2024
4b7e458
aa
dimaMachina Dec 11, 2024
777eac5
aa
dimaMachina Dec 11, 2024
3786aca
aa
dimaMachina Dec 11, 2024
e1260f4
aa
dimaMachina Dec 11, 2024
1c5c46f
aa
dimaMachina Dec 11, 2024
16424ae
aa
dimaMachina Dec 11, 2024
dae03ba
aa
dimaMachina Dec 11, 2024
e1b3cc5
aa
dimaMachina Dec 11, 2024
67a2250
aa
dimaMachina Dec 11, 2024
2be769b
[skip ci]
dimaMachina Dec 13, 2024
785c103
fix
dimaMachina Dec 13, 2024
9a0a3cd
migrate `graphiql` from `jest` to `vitest`
dimaMachina Dec 13, 2024
a862023
add .js extension
dimaMachina Dec 13, 2024
3f3472a
add .js extension
dimaMachina Dec 13, 2024
5fd2901
Merge branch 'do-not-bundle-codemirror' into graphiql-vitest
dimaMachina Dec 13, 2024
be801e4
upd
dimaMachina Dec 13, 2024
398b087
upd
dimaMachina Dec 13, 2024
a337e82
Merge branch 'do-not-bundle-codemirror' into graphiql-vitest
dimaMachina Dec 13, 2024
731082d
upd
dimaMachina Dec 13, 2024
f69cd78
upd
dimaMachina Dec 13, 2024
ce223e3
upd
dimaMachina Dec 13, 2024
6f6f481
upd
dimaMachina Dec 13, 2024
a04d46d
upd
dimaMachina Dec 13, 2024
1be7078
Merge branch 'do-not-bundle-codemirror' into react-compiler
dimaMachina Dec 13, 2024
adf7725
Merge branch 'graphiql-vitest' into react-compiler
dimaMachina Dec 13, 2024
d6f62d4
upd
dimaMachina Dec 13, 2024
3ecae05
upd
dimaMachina Dec 13, 2024
8092f10
upd
dimaMachina Dec 13, 2024
24c8c1e
Merge branch 'main' into react-compiler
dimaMachina Dec 14, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/hip-cycles-agree.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@graphiql/react': minor
---

compile source code with react-compiler, remove `useMemo` and `useCallback` usages
15 changes: 15 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,21 @@ module.exports = {
'promise/prefer-await-to-then': 'error',
},
},
{
files: ['packages/graphiql-react/**'],
plugins: ['react-compiler'],
rules: {
'@typescript-eslint/no-restricted-imports': [
'error',
...RESTRICTED_IMPORTS,
{
name: 'react',
importNames: ['memo', 'useCallback', 'useMemo'],
},
],
'react-compiler/react-compiler': 'error',
},
},
{
// Monaco-GraphQL rules
files: ['packages/monaco-graphql/**'],
Expand Down
7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@
"gen-agenda": "wgutils agenda gen"
},
"dependencies": {
"eslint-plugin-react-compiler": "19.0.0-beta-37ed2a7-20241206",
"graphql-http": "^1.22.1",
"@babel/cli": "^7.21.0",
"@babel/core": "^7.21.0",
Expand Down Expand Up @@ -109,16 +110,16 @@
"concurrently": "^7.0.0",
"copy": "^0.3.2",
"cspell": "^5.15.2",
"eslint": "^9.7.0",
"eslint": "9.14.0",
"eslint-config-prettier": "^9.1.0",
"eslint-import-resolver-typescript": "^3.6.1",
"eslint-plugin-cypress": "^3.4.0",
"eslint-plugin-import-x": "^3.1.0",
"eslint-plugin-jest": "^28.6.0",
"eslint-plugin-mdx": "^3.1.5",
"eslint-plugin-promise": "^7.0.0",
"eslint-plugin-react": "^7.35.0",
"eslint-plugin-react-hooks": "^5.1.0-rc-76002254-20240724",
"eslint-plugin-react": "^7.37.2",
"eslint-plugin-react-hooks": "^5.1.0",
"eslint-plugin-sonar": "^0.14.1",
"eslint-plugin-sonarjs": "^1.0.4",
"eslint-plugin-unicorn": "^55.0.0",
Expand Down
2 changes: 2 additions & 0 deletions packages/graphiql-react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
"react-dom": "^16.8.0 || ^17 || ^18"
},
"dependencies": {
"react-compiler-runtime": "19.0.0-beta-37ed2a7-20241206",
"@graphiql/toolkit": "^0.11.0",
"@headlessui/react": "^1.7.15",
"@radix-ui/react-dialog": "^1.0.4",
Expand All @@ -66,6 +67,7 @@
"set-value": "^4.1.0"
},
"devDependencies": {
"babel-plugin-react-compiler": "19.0.0-beta-37ed2a7-20241206",
"@types/react-dom": "^18.3.1",
"@babel/helper-string-parser": "^7.19.4",
"@testing-library/dom": "^10.4.0",
Expand Down
2 changes: 2 additions & 0 deletions packages/graphiql-react/src/editor/common.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
'use no memo';

import { KeyMap } from './types';
import { isMacOs } from '../utility/is-macos';

Expand Down
2 changes: 2 additions & 0 deletions packages/graphiql-react/src/editor/completion.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
'use no memo';

import type { Editor, EditorChange } from 'codemirror';
import type { IHint } from 'codemirror-graphql/hint';
import {
Expand Down
2 changes: 2 additions & 0 deletions packages/graphiql-react/src/editor/components/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
'use no memo';

export { HeaderEditor } from './header-editor';
export { ImagePreview } from './image-preview';
export { QueryEditor } from './query-editor';
Expand Down
219 changes: 84 additions & 135 deletions packages/graphiql-react/src/editor/context.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,7 @@
visit,
} from 'graphql';
import { VariableToType } from 'graphql-language-service';
import {
ReactNode,
useCallback,
useEffect,
useMemo,
useRef,
useState,
} from 'react';
import { ReactNode, useEffect, useRef, useState } from 'react';

import { useStorageContext } from '../storage';
import { createContextHook, createNullableContext } from '../utility/context';
Expand Down Expand Up @@ -329,7 +322,7 @@

const [tabState, setTabState] = useState<TabsState>(initialState.tabState);

const setShouldPersistHeaders = useCallback(
const setShouldPersistHeaders = // eslint-disable-line react-hooks/exhaustive-deps -- false positive, function is optimized by react-compiler, no need to wrap with useCallback
(persist: boolean) => {
if (persist) {
storage?.set(STORAGE_KEY_HEADERS, headerEditor?.getValue() ?? '');
Expand All @@ -341,9 +334,7 @@
}
setShouldPersistHeadersInternal(persist);
storage?.set(PERSIST_HEADERS_STORAGE_KEY, persist.toString());
},
[storage, tabState, headerEditor],
);
};

const lastShouldPersistHeadersProp = useRef<boolean | undefined>();
useEffect(() => {
Expand All @@ -369,7 +360,7 @@
defaultHeaders,
});

const addTab = useCallback<EditorContextType['addTab']>(() => {
const addTab: EditorContextType['addTab'] = () => {

Check warning on line 363 in packages/graphiql-react/src/editor/context.tsx

View check run for this annotation

Codecov / codecov/patch

packages/graphiql-react/src/editor/context.tsx#L363

Added line #L363 was not covered by tests
setTabState(current => {
// Make sure the current tab stores the latest values
const updatedValues = synchronizeActiveTabValues(current);
Expand All @@ -388,93 +379,71 @@
onTabChange?.(updated);
return updated;
});
}, [
defaultHeaders,
defaultQuery,
onTabChange,
setEditorValues,
storeTabs,
synchronizeActiveTabValues,
]);

const changeTab = useCallback<EditorContextType['changeTab']>(
index => {
setTabState(current => {
const updated = {
...current,
activeTabIndex: index,
};
storeTabs(updated);
setEditorValues(updated.tabs[updated.activeTabIndex]);
onTabChange?.(updated);
return updated;
});
},
[onTabChange, setEditorValues, storeTabs],
);
};

const moveTab = useCallback<EditorContextType['moveTab']>(
newOrder => {
setTabState(current => {
const activeTab = current.tabs[current.activeTabIndex];
const updated = {
tabs: newOrder,
activeTabIndex: newOrder.indexOf(activeTab),
};
storeTabs(updated);
setEditorValues(updated.tabs[updated.activeTabIndex]);
onTabChange?.(updated);
return updated;
});
},
[onTabChange, setEditorValues, storeTabs],
);
const changeTab: EditorContextType['changeTab'] = index => {
setTabState(current => {
const updated = {

Check warning on line 386 in packages/graphiql-react/src/editor/context.tsx

View check run for this annotation

Codecov / codecov/patch

packages/graphiql-react/src/editor/context.tsx#L384-L386

Added lines #L384 - L386 were not covered by tests
...current,
activeTabIndex: index,
};
storeTabs(updated);
setEditorValues(updated.tabs[updated.activeTabIndex]);
onTabChange?.(updated);
return updated;

Check warning on line 393 in packages/graphiql-react/src/editor/context.tsx

View check run for this annotation

Codecov / codecov/patch

packages/graphiql-react/src/editor/context.tsx#L390-L393

Added lines #L390 - L393 were not covered by tests
});
};

const closeTab = useCallback<EditorContextType['closeTab']>(
index => {
setTabState(current => {
const updated = {
tabs: current.tabs.filter((_tab, i) => index !== i),
activeTabIndex: Math.max(current.activeTabIndex - 1, 0),
};
storeTabs(updated);
setEditorValues(updated.tabs[updated.activeTabIndex]);
onTabChange?.(updated);
return updated;
});
},
[onTabChange, setEditorValues, storeTabs],
);
const moveTab: EditorContextType['moveTab'] = newOrder => {
setTabState(current => {
const activeTab = current.tabs[current.activeTabIndex];
const updated = {

Check warning on line 400 in packages/graphiql-react/src/editor/context.tsx

View check run for this annotation

Codecov / codecov/patch

packages/graphiql-react/src/editor/context.tsx#L397-L400

Added lines #L397 - L400 were not covered by tests
tabs: newOrder,
activeTabIndex: newOrder.indexOf(activeTab),
};
storeTabs(updated);
setEditorValues(updated.tabs[updated.activeTabIndex]);
onTabChange?.(updated);
return updated;

Check warning on line 407 in packages/graphiql-react/src/editor/context.tsx

View check run for this annotation

Codecov / codecov/patch

packages/graphiql-react/src/editor/context.tsx#L404-L407

Added lines #L404 - L407 were not covered by tests
});
};

const closeTab: EditorContextType['closeTab'] = index => {
setTabState(current => {
const updated = {
tabs: current.tabs.filter((_tab, i) => index !== i),

Check warning on line 414 in packages/graphiql-react/src/editor/context.tsx

View check run for this annotation

Codecov / codecov/patch

packages/graphiql-react/src/editor/context.tsx#L411-L414

Added lines #L411 - L414 were not covered by tests
activeTabIndex: Math.max(current.activeTabIndex - 1, 0),
};
storeTabs(updated);
setEditorValues(updated.tabs[updated.activeTabIndex]);
onTabChange?.(updated);
return updated;

Check warning on line 420 in packages/graphiql-react/src/editor/context.tsx

View check run for this annotation

Codecov / codecov/patch

packages/graphiql-react/src/editor/context.tsx#L417-L420

Added lines #L417 - L420 were not covered by tests
});
};

const updateActiveTabValues = useCallback<
EditorContextType['updateActiveTabValues']
>(
const updateActiveTabValues: EditorContextType['updateActiveTabValues'] =
partialTab => {
setTabState(current => {
const updated = setPropertiesInActiveTab(current, partialTab);
storeTabs(updated);
onTabChange?.(updated);
return updated;
});
},
[onTabChange, storeTabs],
);
};

const { onEditOperationName } = props;
const setOperationName = useCallback<EditorContextType['setOperationName']>(
const setOperationName: EditorContextType['setOperationName'] =
operationName => {
if (!queryEditor) {
return;
}

queryEditor.operationName = operationName;
updateQueryEditor(queryEditor, operationName);

Check warning on line 441 in packages/graphiql-react/src/editor/context.tsx

View check run for this annotation

Codecov / codecov/patch

packages/graphiql-react/src/editor/context.tsx#L441

Added line #L441 was not covered by tests
updateActiveTabValues({ operationName });
onEditOperationName?.(operationName);
},
[onEditOperationName, queryEditor, updateActiveTabValues],
);
};

const externalFragments = useMemo(() => {
const externalFragments = (() => {

Check warning on line 446 in packages/graphiql-react/src/editor/context.tsx

View check run for this annotation

Codecov / codecov/patch

packages/graphiql-react/src/editor/context.tsx#L446

Added line #L446 was not covered by tests
const map = new Map<string, FragmentDefinitionNode>();
if (Array.isArray(props.externalFragments)) {
for (const fragment of props.externalFragments) {
Expand All @@ -492,74 +461,54 @@
);
}
return map;
}, [props.externalFragments]);
})();

const validationRules = useMemo(
() => props.validationRules || [],
[props.validationRules],
);
const validationRules = props.validationRules || [];

const value = useMemo<EditorContextType>(
() => ({
...tabState,
addTab,
changeTab,
moveTab,
closeTab,
updateActiveTabValues,

headerEditor,
queryEditor,
responseEditor,
variableEditor,
setHeaderEditor,
setQueryEditor,
setResponseEditor,
setVariableEditor,

setOperationName,

initialQuery: initialState.query,
initialVariables: initialState.variables,
initialHeaders: initialState.headers,
initialResponse: initialState.response,

externalFragments,
validationRules,
const value: EditorContextType = {

Check warning on line 468 in packages/graphiql-react/src/editor/context.tsx

View check run for this annotation

Codecov / codecov/patch

packages/graphiql-react/src/editor/context.tsx#L468

Added line #L468 was not covered by tests
...tabState,
addTab,
changeTab,
moveTab,
closeTab,
updateActiveTabValues,

shouldPersistHeaders,
setShouldPersistHeaders,
}),
[
tabState,
addTab,
changeTab,
moveTab,
closeTab,
updateActiveTabValues,

headerEditor,
queryEditor,
responseEditor,
variableEditor,
headerEditor,
queryEditor,
responseEditor,
variableEditor,
setHeaderEditor,
setQueryEditor,
setResponseEditor,
setVariableEditor,

setOperationName,
setOperationName,

initialState,
initialQuery: initialState.query,
initialVariables: initialState.variables,
initialHeaders: initialState.headers,
initialResponse: initialState.response,

externalFragments,
validationRules,
externalFragments,
validationRules,

shouldPersistHeaders,
setShouldPersistHeaders,
],
);
shouldPersistHeaders,
setShouldPersistHeaders,
};

return (
<EditorContext.Provider value={value}>{children}</EditorContext.Provider>
);
}

// To make react-compiler happy, otherwise it fails due mutating props
function updateQueryEditor(
queryEditor: CodeMirrorEditorWithOperationFacts,
operationName: string,
) {
queryEditor.operationName = operationName;

Check warning on line 509 in packages/graphiql-react/src/editor/context.tsx

View check run for this annotation

Codecov / codecov/patch

packages/graphiql-react/src/editor/context.tsx#L508-L509

Added lines #L508 - L509 were not covered by tests
}

export const useEditorContext = createContextHook(EditorContext);

const PERSIST_HEADERS_STORAGE_KEY = 'shouldPersistHeaders';
Expand Down
Loading
Loading