I’m struggling for days now with a setup I’d thought would be easy and reusable:
I’m building an App with Ionic 5 + React, which has kind of a news feed, where multiple kind of content comes together. But not exactly the way like in Facebook, it has different sections for each kind of content (like events, news, etc.).
They all act similar: each section has a title, shows the first n items and then a “Show more” link. Of course a click on one of these items immediatly brings the user to the detail page. But a click on “Show more” should bring the user to a page with only that specific list in expanded form (instead of let’s say the first 3 items there should be 50 and when reaching the end of that list it should load the next 50 and so on).
Because the APIs that deliver each kind of content use different structures, the page on which that “section component” is embedded passes two functions, sourceFn
and mapFn
, to that component. sourceFn
handles loading of that n items while mapFn
takes an item and maps that API data structure to the fields that are needed for the reused section component to render it’s list items.
So far so good, it works. But I’m stuck at the “Show more” link. Because here that embedded section redirects to another page, which dynamically displays the expanded list, it need’s to know the corresponding two functions sourceFn
and mapFn
. I tried many approaches (like https://stackoverflow.com/a/52064362) but every single one failed. Some times it says that somewhere props
is unknown, but mainly because of DataCloneError: The Object could not be cloned
I’m happy for every hint, how it could be done (or done better)
Here are some approaches I tried:
(Please let me know in a comment, whether to post more code. I don’t want to spam 0:) )
<Link to={'/page/list'+ id} id={id} title={title} sourceFn={sourceFn} mapFn={mapFn}>
<IonButton slot="end" size="small" fill="clear" routerDirection="forward">
Show more
<IonIcon icon={chevronForwardOutline} slot="end" />
</IonButton>
</Link>
<Link to={{
pathname: '/page/list'+ id,
state: {id: id, title: title, sourceFn: sourceFn, mapFn: mapFn}
}}>
<IonButton slot="end" size="small" fill="clear" routerDirection="forward">
Show more
<IonIcon icon={chevronForwardOutline} slot="end" />
</IonButton>
</Link>
and the Route in App.tsx
:
<Route
exact={true}
path={"/page/list/:sectionid"}
render={(props) =>
<List
id={props.location.state.id}
title={props.location.state.title}
sourceFn={props.location.state.sourceFn}
mapFn={props.location.state.mapFn}
/>}
/>
and also simply
<Route exact={true} path={"/page/list/:sectionid"} component={List} />
2
Answers
I think this calls for Context.
The parent component can have a context at the level where sourceFn and mapFn come from:
then in your List component, you can do:
and as you said, your route would simply be:
I would suggest the
React.Context
approach but you can also just pass the names of the functions as parameter names like thisIn Your function helper library map all of the functions so they can be accessed by the specific name.
then when you need a function, you can use the name of the function to access it in the function map