New Jan 5, 2025

How to propagate generics when using render prop function

Libraries, Frameworks, etc. All from Newest questions tagged reactjs - Stack Overflow View How to propagate generics when using render prop function on stackoverflow.com

I am currently creating a Compound Component type component. At that time I am looking for a way to propagate generics when using render prop.

interface ListContextValue<T> {
  rows: T[];
}

const createListContext = once(<T,>() => createContext<ListContextValue<T> | undefined>(undefined) );

const useListContext = <T,>() => { const context = useContext(createListContext<T>()); if (!context) { throw new Error( "useInfiniteList must be used within an InfiniteListProvider" ); } return context; };

interface ListProps<T> { rows: T[]; children?: React.ReactNode; }

export const List = <T,>({ rows, children }: ListProps<T>) => { const ListContext = createListContext<T>();

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

export interface ListContainerProps<T> extends Omit<SlotProps, "children"> { children?: (props: { row: T }) => React.ReactNode; }

export const ListContainer = <T,>({ children }: ListContainerProps<T>) => { const { rows } = useListContext<T>();

return ( <div> {rows.map((row) => { return children ? children({ row }) : null; })} </div> ); };

Above is the List component code.

export default function UserList() {
  return (
    <List rows={rows}>
      <ListContainer>
        {({ row }) => (
          <div>
            {/** row is unknown type */}
            {row}
          </div>
        )}
      </ListContainer>
    </List>
  );
}

When using the component, is it possible to automatically infer the row type in the render prop function?

export default function UserList() {
  return (
    <List<User[]> rows={rows}>
      <ListContainer<User>>
        {({ row }) => (
          <div>
            {row}
          </div>
        )}
      </ListContainer>
    </List>
  );
}

Of course, it can be solved this way, but I don't think it's a good way.

Scroll to top