react-accessible-treeview icon indicating copy to clipboard operation
react-accessible-treeview copied to clipboard

Metadata type not inferred from supplied data.

Open airtonix opened this issue 1 year ago • 4 comments

Describe the bug

Despite #193 claiming it fixed this issue, installing 2.10.0 reveals that:

  • <TreeView<CustomMetaDataType> /> is not possible
  • <TreeView data={myFlatListOfTypedItems} nodeRenderer={(element) => (...)} /> doesn't infer the type from my items and enforces the default type for metadata.

the index.d.ts has this at the bottom:

declare const TreeView: React.ForwardRefExoticComponent<ITreeViewProps<IFlatMetadata> & React.RefAttributes<HTMLUListElement>>;
export default TreeView;

Which basically just decides it doesn't care what kind of pizza you ordered, you're getting a Margherita.

https://github.com/user-attachments/assets/099c5596-7744-45e2-b037-52dc3366c72f

Where my TocLeaf looks like

type TocLeaf = Omit<INode<{ href: string }>, 'id'> & { id: string };

Code That Causes The Issue

When using forward ref and expecting to allow others to utilise the generic type parameter, you need to do two things:

  1. Not define the component inline with the forwardRef function, instead define it outside with two parameters: props, and ref
  2. use this defined function reference in an exported implementation of forwardRef that is typecast with the return value of function in 1.:
export interface ComponentRef {
  foo: VoidFunction;
}

export type ComponentProps<T> = {
  data: T[];
  onSomething: (data: T) => void;
};

const Component = <T,>(props: ComponentProps<T>, ref: Ref<ComponentRef>) => {
  const foo = useCallback(() => {
    console.log(props.data);
  }, [props]);

  useImperativeHandle(ref, () => ({
    foo,
  }));

  return <div>{props.data.length}</div>;
};

const WithForwardedGeneric = forwardRef(Component) as <T>(
  props: ComponentProps<T> & { ref?: Ref<ComponentRef> }
) => ReturnType<typeof Component>;

export const Foo = () => {
  return (
    <WithForwardedGeneric<{ yes: false }>
      data={[]}
      onSomething={(data) => console.log(data)}
    />
  );
};

image

So to put this in context:

export interface TreeviewComponentRef {
  foo: VoidFunction;
}

// existing types for tree view props. no change needed
export type ITreeViewProps<M extends IFlatMetadata = IFlatMetadata> = { ... }

// 1. define component outside of forwardRef
const TreeViewComponent = <T,>(props: ITreeViewProps<T>, ref: Ref<TreeviewComponentRef>) => {...};

// 2. export the forwardRef, with an enforced type generic and return type.
const TreeView = forwardRef(TreeViewComponent) as <T>(
  props: ITreeViewProps<T> & { ref?: Ref<TreeviewComponentRef> }
) => ReturnType<typeof TreeViewComponent>;

// example using it.
export const MyAmazingApp = () => {
  return (
    <TreeView<{ yes: false }>
      data={[]}
      nodeRenderer={(element) => console.log(data.metadata.yes === false)}
    />
  );
};

However, I'm not smart enough to work out how to make this work with your use of propTypes (i haven't used that concept for nearly 6 years now)

To Reproduce Steps to reproduce the behavior:

  1. Go to '...'
  2. Click on '....'
  3. Scroll down to '....'
  4. See error

Expected behavior A clear and concise description of what you expected to happen.

Screenshots If applicable, add screenshots to help explain your problem.

Desktop (please complete the following information):

  • OS: [e.g. iOS]
  • Browser [e.g. chrome, safari]
  • Version [e.g. 22]

Smartphone (please complete the following information):

  • Device: [e.g. iPhone6]
  • OS: [e.g. iOS8.1]
  • Browser [e.g. stock browser, safari]
  • Version [e.g. 22]

Additional context Add any other context about the problem here.

airtonix avatar Dec 23 '24 08:12 airtonix

Thanks for the detailed report. The team and I are on vacation for at least a week. But they’ll look at it when we get back.

If you are willing to make a PR, that will speed things up.

cc @mellis481 @yhy-1

dgreene1 avatar Dec 23 '24 14:12 dgreene1

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] avatar Feb 21 '25 18:02 stale[bot]

This issue was closed automatically since it was marked as stale because it has not had recent activity. Thank you for your contributions.

stale[bot] avatar Mar 01 '25 00:03 stale[bot]

@yhy-1 do you know if a fix for this is planned?

dgreene1 avatar Mar 01 '25 01:03 dgreene1

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] avatar Apr 30 '25 02:04 stale[bot]

This issue was closed automatically since it was marked as stale because it has not had recent activity. Thank you for your contributions.

stale[bot] avatar May 07 '25 03:05 stale[bot]