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

Upgrade to React 18 #1100

Draft
wants to merge 15 commits into
base: main
Choose a base branch
from
Draft

Upgrade to React 18 #1100

wants to merge 15 commits into from

Conversation

jernestmyers
Copy link
Member

No description provided.

@dmfalke
Copy link
Member

dmfalke commented Jun 27, 2024

Regarding ReactDOM.unmountComponentAtNode, this goes hand-in-hand with ReactDOM.render. Per https://react.dev/blog/2022/03/08/react-18-upgrade-guide#updates-to-client-rendering-apis, you should be able to replace those instances with root.unmount(). This might involve adding an instance property to class based components, in order to keep track of root.

@dmfalke
Copy link
Member

dmfalke commented Jun 27, 2024

As noted elsewhere, ReactDOM.findDOMNode is deprecated. In most cases, this can be replaced with a ref. This can be a follow-up task. Just noting here for posterity.

❯ rg findDOMNode -l
packages/libs/wdk-client/src/Components/InputControls/IndeterminateCheckbox.tsx
packages/libs/wdk-client/src/Components/Loading/Loading.tsx
packages/libs/wdk-client/src/Components/Overlays/Popup.tsx
packages/libs/wdk-client/src/Components/Display/Sticky.jsx
packages/libs/wdk-client/src/Controllers/LegacyParamController.tsx
packages/libs/wdk-client/src/Components/AttributeFilter/FieldList.jsx
packages/libs/wdk-client/src/Components/AttributeFilter/Histogram.jsx
packages/libs/wdk-client/src/Views/Answer/AnswerFilter.jsx
packages/libs/wdk-client/src/Views/Records/RecordUI.jsx

Copy link
Member

@dmfalke dmfalke left a comment

Choose a reason for hiding this comment

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

I've reviewed the code changes, and it looks really great. I made some nitpicky suggestions, mostly related to keeping things as type-safe as possible. Let me know what you think!

@@ -26,7 +26,7 @@ type FacetedPiePlotProps = Omit<

const FacetedPiePlot = (facetedPiePlotProps: FacetedPiePlotProps) => {
const { componentProps } = facetedPiePlotProps;
const onPlotlyRender = useCallback((_, graphDiv) => {
const onPlotlyRender = useCallback((_: any, graphDiv: HTMLElement) => {
Copy link
Member

Choose a reason for hiding this comment

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

Let's use unknown instead of any. It's a safer type to use, especially in this case where we don't want do anything with the parameter.

@@ -14,7 +14,7 @@ export default {
const ControlledTemplate: Story<DateInputProps> = (args) => {
const [value, setValue] = useState<string>('2005-01-03');
const onValueChange = useCallback(
(newValue) => {
(newValue: any) => {
Copy link
Member

Choose a reason for hiding this comment

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

Should the type of newValue be string | undefined?

@@ -21,15 +21,15 @@ export const ControlledLinked: Story<DateRangeInputProps> = () => {
// there must be a cleverer way to do this
// avoiding the cut and paste
const handleChangeA = useCallback(
(newRange) => {
(newRange: any) => {
Copy link
Member

Choose a reason for hiding this comment

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

Ideally, this would be DateRange, but the expected type is DateOrNumberRange. I suppose we can switch this to DateOrNumberRange and then check that it is a DataRange and throw an error (or return early) if not. But let's just leave it as any for now.

Ultimately, we should fix DateRange to use the correct types, but that's beyond the scope of this PR.

@@ -14,7 +14,7 @@ export default {
const ControlledTemplate: Story<NumberInputProps> = (args) => {
const [value, setValue] = useState<number | undefined>(args.value ?? 1);
const onValueChange = useCallback(
(newValue) => {
(newValue: any) => {
Copy link
Member

Choose a reason for hiding this comment

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

Similar comment as above, about DateRange.

@@ -337,7 +337,7 @@ export function HistogramFilter(props: Props) {
className="filter-param"
style={{ position: 'relative', marginTop: '2em' }}
>
{data.error && <pre>{String(data.error)}</pre>}
<>{data.error && <pre>{String(data.error)}</pre>}</>
Copy link
Member

Choose a reason for hiding this comment

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

This could be changed to:

Suggested change
<>{data.error && <pre>{String(data.error)}</pre>}</>
{data.error != null && <pre>{String(data.error)}</pre>}

Comment on lines +79 to +114
<>
<div className={cx('-ProviderLabelPrefix')}>
<i>
Original variable{' '}
{MultiFilterVariable.is(variable) ? 'names' : 'name'}:
</i>
</div>
{/* showing three variables for multifilter or single variable */}
&nbsp;{threeProviderLabel}
{/* generalize Show/Hide more: there is a case that providerLabel is string */}
{Array.isArray(providerLabel) && providerLabel.length > 3 ? (
<>
{showMore && providerLabelLeftover}
&nbsp;
<HelpIcon>
The name of this variable in the original data files
</HelpIcon>
&nbsp;&nbsp;
<button
className="variable-show-more-link link"
onClick={() => {
setShowMore(!showMore);
}}
>
{showMoreLink}
</button>
</>
) : (
<>
&nbsp;
<HelpIcon>
The name of this variable in the original data files
</HelpIcon>
</>
)}
</>
Copy link
Member

Choose a reason for hiding this comment

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

We can isolate the use of the fragment to the text node.

Suggested change
<>
<div className={cx('-ProviderLabelPrefix')}>
<i>
Original variable{' '}
{MultiFilterVariable.is(variable) ? 'names' : 'name'}:
</i>
</div>
{/* showing three variables for multifilter or single variable */}
&nbsp;{threeProviderLabel}
{/* generalize Show/Hide more: there is a case that providerLabel is string */}
{Array.isArray(providerLabel) && providerLabel.length > 3 ? (
<>
{showMore && providerLabelLeftover}
&nbsp;
<HelpIcon>
The name of this variable in the original data files
</HelpIcon>
&nbsp;&nbsp;
<button
className="variable-show-more-link link"
onClick={() => {
setShowMore(!showMore);
}}
>
{showMoreLink}
</button>
</>
) : (
<>
&nbsp;
<HelpIcon>
The name of this variable in the original data files
</HelpIcon>
</>
)}
</>
<div className={cx('-ProviderLabelPrefix')}>
<i>
Original variable{' '}
{MultiFilterVariable.is(variable) ? 'names' : 'name'}:
</i>
</div>
{/* showing three variables for multifilter or single variable */}
<>&nbsp;{threeProviderLabel}</>
{/* generalize Show/Hide more: there is a case that providerLabel is string */}
{Array.isArray(providerLabel) && providerLabel.length > 3 ? (
<>
{showMore && providerLabelLeftover}
&nbsp;
<HelpIcon>
The name of this variable in the original data files
</HelpIcon>
&nbsp;&nbsp;
<button
className="variable-show-more-link link"
onClick={() => {
setShowMore(!showMore);
}}
>
{showMoreLink}
</button>
</>
) : (
<>
&nbsp;
<HelpIcon>
The name of this variable in the original data files
</HelpIcon>
</>
)}

@@ -15,7 +15,7 @@ interface Props {
isCollapsed?: boolean;
onCollapsedChange: (isCollapsed: boolean) => void;
headerContent: React.ReactNode;
headerComponent?: React.ReactType;
headerComponent?: React.FC | React.ComponentType;
Copy link
Member

Choose a reason for hiding this comment

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

ComponentType is a union of ComponentClass and FunctionComponent.

Suggested change
headerComponent?: React.FC | React.ComponentType;
headerComponent?: React.ComponentType;

@@ -81,7 +89,7 @@ export function LegacyMapRedirectHandler({
const additionalAnalysisConfig = {
...baseAdditionalAnalysisConfig,
...descriptorConfig,
};
} as AdditionalAnalysisConfig;
Copy link
Member

Choose a reason for hiding this comment

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

Instead of using as, we should declare the type of the variable:

const additionalAnalysisConfig: AdditionalAnalysisConfig = {

This will require declare the components that make up this value (baseAdditionalAnalysisConfig, and descriptorConfig). I think this will reveal a subtle type conflict.

Generally, we should avoid as if possible, and document why we are using it if we need it. This isn't something we've really enforced before.

@@ -26,6 +26,8 @@ export function Downloads() {
[history, location, match]
);

console.log('version:', React.version);
Copy link
Member

Choose a reason for hiding this comment

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

Can we remove this?

chromosomes
</div>
);
export const EmptyChromosomesFilter: React.FunctionComponent<EmptyChromosomesFilterProps> =
Copy link
Member

Choose a reason for hiding this comment

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

Should we use React.FC to be consistent with other packages?

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.

None yet

2 participants