-
-
Notifications
You must be signed in to change notification settings - Fork 25
Description
Hi, thanks for building this, it fills an important need for us! I'm opening this as a new issue but having typed it up, it might be more of a feature request. Gonna leave it as is because it's both a request for advice and a proposal for an update.
I'm trying to this library within an existing FlashList and running into trouble because one should not embed a FlatList in an existing virtualized list. It appears I can copy/paste the list setup logic in Markdown.tsx to configure and feed elements into an existing List since there's a lot of overlapping logic. If that's the case, there might be a good opportunity to refactor so the core rendering logic is exposed in a hook and any list can consume it:
// Code copied/pasted from Markdown.tsx into a new hook
export function useMarkdownListData({ value, baseUrl, renderer, tokenizer }: MarkdownProps) {
const colorScheme = useColorScheme();
const rnElements = useMarkdown(value, {
theme,
baseUrl,
renderer,
colorScheme,
styles,
tokenizer,
});
const renderItem = useCallback(({ item }: { item: ReactNode }) => {
return item as ReactElement;
}, []);
const keyExtractor = useCallback((_: ReactNode, index: number) => index.toString(), []);
return { keyExtractor, renderItem, rnElements };
}
In my case, I used a custom hook with that code and then passed the data straight into my list. Here are relevant portions simplified.
// in the body
const { keyExtractor, renderItem, rnElements } = useMarkdownListData({
value: serverAlbum.notesMarkdown || '',
});
const listData = useMemo((): ListItem[] => {
return [
{ type: 'header' as const, data: () => HeaderComponent },
{ type: 'controls' as const, data: () => ControlsComponent },
{ type: 'footer' as const, data: () => FooterComponent },
...rnElements.map((element) => ({ type: 'markdown' as const, data: element })), // <----- the one we care about here
];
}, [HeaderComponent, FooterComponent, ControlsComponent]);
// Later on, FlashList props
keyExtractor={(item, index) => {
switch (item.type) {
case 'header':
case 'controls':
case 'footer': {
return item.type;
}
case 'markdown': { // <------ the one we care about here
return keyExtractor(item.data, index);
}
}
}}
renderItem={({ item }) => {
switch (item.type) {
case 'header':
case 'controls':
case 'footer': {
return item.data();
}
case 'markdown': { // <------ the one we care about here
return renderItem({ item: item.data });
}
}
}}
This will decouple the setup logic from the actual list presentation logic. It wouldn't change this library other than by exposing a hook that isolates the exact code you're already using, you'd just have to commit to exposing elements from your hook that are generic enough that others could use them.
Is this something you're open to? I can provide a PR.