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

Bugfix: clean treeselectionview type and fix a initial state check grid samples issue #5053

Merged
merged 8 commits into from
Nov 6, 2024
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
import { Box, Checkbox, FormControlLabel, IconButton } from "@mui/material";
import React, { useEffect } from "react";
import { ViewPropsType } from "../utils/types";
import { useUnboundState } from "@fiftyone/state";

interface CheckedState {
[key: string]: {
Expand Down Expand Up @@ -70,6 +71,13 @@ export default function TreeSelectionView(props: ViewPropsType) {
const [checkedState, setCheckedState] =
React.useState<CheckedState>(initialCheckedState);

const unboundState = useUnboundState(checkedState);

// useEffect(() => {
Copy link
Contributor

Choose a reason for hiding this comment

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

If you are confident this useEffect is no longer needed, you can probably just delete it @lanzhenw - it looks like it is just a console.log() anyway

Copy link
Contributor Author

Choose a reason for hiding this comment

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

removed.

// console.log('unboundState useEffect', unboundState)
// // no need to call onChange here, because the change comes from python side
// }, [data, unboundState])

Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Remove unused unboundState or document its purpose

The unboundState is created but never used in the component. The commented useEffect suggests it's related to Python-side synchronization, but its purpose isn't clear. This could lead to unnecessary re-renders and memory allocation.

Either:

  1. Remove the unused state:
-  const unboundState = useUnboundState(checkedState);
-
-  // useEffect(() => {
-  //   console.log('unboundState useEffect', unboundState)
-  //   // no need to call onChange here, because the change comes from python side
-  // }, [data, unboundState])
  1. Or document its purpose and implement the intended functionality.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const unboundState = useUnboundState(checkedState);
// useEffect(() => {
// console.log('unboundState useEffect', unboundState)
// // no need to call onChange here, because the change comes from python side
// }, [data, unboundState])

// Initialize collapsed state for all parents
const initialCollapsedState: CollapsedState = React.useMemo(() => {
const state: CollapsedState = {};
Expand Down Expand Up @@ -192,6 +200,16 @@ export default function TreeSelectionView(props: ViewPropsType) {
return idx === -1 ? 0 : idx + 1;
};

useEffect(() => {
const sampleIds = view?.data.flatMap(([parentId, children]) => {
return children.map((childId) =>
typeof childId === "string" ? childId : childId[0]
);
});
onChange(path, sampleIds);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
Comment on lines +198 to +206
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Refactor duplicate initialization logic and fix effect dependencies

The useEffect duplicates the initialization logic from the early return block and has several issues:

  1. Potential race condition with the early return logic
  2. Missing dependencies in the effect's dependency array
  3. Unconditional state update on mount

Consider refactoring to:

- useEffect(() => {
-   const sampleIds = view?.data.flatMap(([parentId, children]) => {
-     return children.map((childId) =>
-       typeof childId === "string" ? childId : childId[0]
-     );
-   });
-   onChange(path, sampleIds);
-   // eslint-disable-next-line react-hooks/exhaustive-deps
- }, []);

+ useEffect(() => {
+   if (data === undefined && view?.data) {
+     const sampleIds = view.data.flatMap(([parentId, children]) => {
+       return children.map((childId) =>
+         typeof childId === "string" ? childId : childId[0]
+       );
+     });
+     onChange(path, sampleIds);
+   }
+ }, [data, view?.data, path, onChange]);

Committable suggestion skipped: line range outside the PR's diff.


// CheckboxView: Represents a single checkbox (either parent or child)
function CheckboxView({
id,
Expand Down
6 changes: 2 additions & 4 deletions fiftyone/operators/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -610,18 +610,16 @@ def tuple(self, name, *items, **kwargs):
self.define_property(name, tuple_type, view=tuple_view, **kwargs)
return tuple_type

def tree(self, name, *items, **kwargs):
def tree(self, name, **kwargs):
"""Defines a tree property on the object.

Args:
name: the name of the property
*items: the types of the items in the tree

Returns:
a :class:`Tree`
"""
tree_selection_view = TreeSelectionView(**kwargs)
tree_type = Object(*items)
tree_type = List(String())
self.define_property(
name, tree_type, view=tree_selection_view, **kwargs
)
Expand Down
Loading