skip to Main Content

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


  1. I think this calls for Context.

    The parent component can have a context at the level where sourceFn and mapFn come from:

    const SomeContext = React.createContext()
    
    export const useContextName = React.useContext(SomeContext)
    
    <SomeContext.Provider value={{ sourceFn, mapFn }}>
      ...your routes here...
    </SomeContext.Provider>
    

    then in your List component, you can do:

    import { useContextName } from 'wherever/you/are/exporting/from'
    
    const List = (...your props ...) => {
       const { sourceFn, mapFn } = useContextName()
       ... the rest of your component ...
    }
    

    and as you said, your route would simply be:

    <Route exact={true} path={"/page/list/:sectionid"} component={List} />
    
    Login or Signup to reply.
  2. I would suggest the React.Context approach but you can also just pass the names of the functions as parameter names like this

    <Route exact={true} 
      path={"/page/list/:mapFuncName/:sourceFuncName/:sectionid"} 
      component={List} />
    

    In Your function helper library map all of the functions so they can be accessed by the specific name.

    mapFuncMap : {
      func1 : ()=> {}
      func2 : ()=> {}
      func3 : ()=> {}
    }
    
    sourceFuncMap : {
      func1 : ()=> {}
      func2 : ()=> {}
      func3 : ()=> {}
    }
    

    then when you need a function, you can use the name of the function to access it in the function map

    sourceFuncMap['func1']();
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search