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

feature: EuiDataGrid type improvements to support React 18 #6958

Conversation

tkajtoch
Copy link
Member

@tkajtoch tkajtoch commented Jul 18, 2023

Summary

@types/react for React 18 introduced a few breaking changes, primarily in the automatic type inference area. Specifically, type inference for useCallback when passing to typed props is broken in TS version we're using (it should be fixed in v5.2 by this PR and possibly more), but we're not there yet and the upgrade isn't straightforward.

React 17 apps using EUI won't be affected by these changes and React 18 apps will work as before depending on the TypeScript version they're running on.

There are also a few small fixes to ensure safe typing in other EuiDataGrid places.

Please pay attention to the JSXElementConstructor changes as it's the one that may cause the most trouble. I made sure the old and new types resolve to almost the same thing, but JSXElementConstructor had to be replaced as it breaks prop type inference when used and creates strange issues throughout our codebase when using @types/react v18. Overall, I think we should standardize whether we accept react elements or components in props in order to make sure we're rendering allowed input types correctly and not just casting the values to either of these in our render functions.

QA

  1. Checkout this branch
  2. Run yarn
  3. Run yarn tsc --noEmit and confirm there are no errors in src/components/datagrid

Remove or strikethrough items that do not apply to your PR.

General checklist

@tkajtoch tkajtoch requested review from cee-chen and a team July 18, 2023 15:27
@tkajtoch tkajtoch self-assigned this Jul 18, 2023
Comment on lines +586 to 590
| ((props: EuiDataGridCellValueElementProps) => ReactNode)
| ComponentClass<EuiDataGridCellValueElementProps>;
renderCellPopover?:
| JSXElementConstructor<EuiDataGridCellPopoverElementProps>
| ((props: EuiDataGridCellPopoverElementProps) => ReactNode);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just curious, why did renderCellPopover not need to be converted from JSXElementConstructor to ComponentClass?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it doesn't throw any errors in our code and I wanted to keep this already complex change as small as possible. We should discuss replacing all JSXElementConstructor usages with more compatible types so it's consistent across the board

Copy link
Contributor

@cee-chen cee-chen Jul 18, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 Gotcha, I can make a follow-up issue for datagrid types related to component typing at a later date.

| JSXElementConstructor<EuiDataGridColumnCellActionProps>
| ((props: EuiDataGridColumnCellActionProps) => ReactNode);
export type EuiDataGridColumnCellAction = (
props: EuiDataGridColumnCellActionProps
Copy link
Contributor

@cee-chen cee-chen Jul 18, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cell actions also need to be able to take class components if necessary (I don't know how many consumsers are still using those, but they're valid and we should accept them type-wise).

Should we consider creating a new shared type for this? Something that takes a set of props as a generic, and then returns either a function component or class component version? We have similar type helpers in src/components/common that might be worth taking a leaf from.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I updated the type to ComponentType<EuiDataGridColumnCellActionProps> which seems to work just fine and checks all the boxes

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! I was experimenting with using ComponentType<> across the board in data_grid_types.ts (d9a9974) and it seemed to work great locally in VSCode - I wasn't getting any reported errors. I did get errors however when I ran yarn tsc along the lines of:

src/components/datagrid/data_grid.test.tsx:2031:11 - error TS2322: Type '({ rowIndex, columnId }: EuiDataGridCellValueElementProps) => string' is not assignable to type 'ComponentType<EuiDataGridCellValueElementProps>'.
  Type '({ rowIndex, columnId }: EuiDataGridCellValueElementProps) => string' is not assignable to type 'FunctionComponent<EuiDataGridCellValueElementProps>'.
    Type 'string' is not assignable to type 'ReactElement<any, any> | null'.

2031           renderCellValue={({ rowIndex, columnId }) =>

Not sure which is reporting more correctly, vscode or CLI 😅 Either way, we can punt investigating that til later, or that commit works locally for you, feel free to cherry-pick it - whatever works!

Copy link
Contributor

@cee-chen cee-chen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall this looks great - I just have 2 change requests. 1 code cleanup in display_selectors.tsx and one bug/change request in data_grid_toolbar.tsx

@@ -33,7 +33,7 @@ export const useInMemoryValues = (
rowCount: number
): [
EuiDataGridInMemoryValues,
(rowIndex: number, columnId: string, value: string) => void
EuiDataGridInMemoryRendererProps['onCellRender']
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Super nice cleanup! 🎉

}

if (position === 'left.prepend') {
return additionalControlsObj.left as ReactNode;
Copy link
Contributor

@cee-chen cee-chen Jul 18, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is missing rendering additionalControls.left.prepend and additionalControls.left.append - you can see several failing data_grid_toolbar tests.

I'm also not a super huge fan personally of the early return syntax; my 2c is that it feels way harder to read and understand what's going on (as evidenced by the failing missed cases 😅). I'm going to take a pass at cleaning this up more and send that your way.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I'm not super proud of this one, I just wanted to give it more structure so TS would be happy. I have no idea how I missed these failing tests, I ran the entire test suite and I'd swear it was green 🤔 Anyway, if you wanna try refactoring it I'd really appreciate it!

Copy link
Contributor

@cee-chen cee-chen Jul 18, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LMK what you think!

https://github.com/tkajtoch/eui/compare/feature/react-18-ts-datagrid-enhancements...cee-chen:eui:feature/react-18-ts-datagrid-enhancements?expand=1

I'm not sure it's a huge improvement, but at least there aren't torturous type ternaries 😅 If you're good with it I can push it up to this branch, or feel free to cherry-pick, up to you.

Also, I made a unrelated typeof boolean change at the very bottom of the file - VSCode was telling me it was a problem locally, although I'm not sure if typescript linting would have said the same 🤷

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your code looks so much better, thank you! I committed it here

@cee-chen
Copy link
Contributor

stale PR check-in - @tkajtoch let me know if you have any questions about the comments I left above, or if you'd like me to push up my change requests directly to this branch to save you some time - happy to do so!

@tkajtoch tkajtoch force-pushed the feature/react-18-ts-datagrid-enhancements branch from d75b55b to 64b47f4 Compare July 24, 2023 21:08
@tkajtoch tkajtoch force-pushed the feature/react-18-ts-datagrid-enhancements branch from 64b47f4 to 6ef48b4 Compare July 24, 2023 22:44
@tkajtoch tkajtoch force-pushed the feature/react-18-ts-datagrid-enhancements branch from 6ef48b4 to 43d487e Compare July 24, 2023 22:45
Copy link
Contributor

@cee-chen cee-chen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the thorough work on this Tomasz! Let's merge this in.

BTW, I may swing a PR for the datagrid component types cleanup by you after this. I'm a little confused because my local VSCode vs local yarn tsc is not quite matching up 🤔

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants