Pass JSX component as child but specifying its params ‘later’

I have a React.js list component that I want to use as a generic list component.
Please see the current list component below:

const RepositoryList = () => {
    ...

    return (
        <div className="admin-container">
            <div className="adminTitle text-center mb-5 fs-3"></div>
            <main>
                { !isLoading && !fetchError && 
                    <div className="col-6 mx-auto">
                        <Table striped bordered hover>
                            <RepositoryListHeader />
                            <tbody>
                                {showedRepositories.map((repository) => (
                                    <RepositoryRow 
                                        key={repository.id} 
                                        record={repository} 
                                        formId={newRepositoryFormId}
                                        handleSave={handleSave}
                                        handleDelete={handleDelete} />
                                ))}
                                ...
    )
}

export default RepositoryList;

So I want the RepositoryListHeader and RepositoryRow to pass to my AdminList component which would look like

const AdminList = ( {headerEl, rowEl, ...} ) => {
    ...

    return (
        <div className="admin-container">
            <div className="adminTitle text-center mb-5 fs-3"></div>
            <main>
                { !isLoading && !fetchError && 
                    <div className="col-6 mx-auto">
                        <Table striped bordered hover>
                            {headerEl}
                            <tbody>
                                {showedRepositories.map((repository) => (
                                    {rowEl}
                                ))}
                                ...
    )
}

export default AdminList;

However I can pass the repository.id, … values (which comes from forEach of showedRepositories) only in AdminList component and not in the parent of AdminList where all the parameter should defined.
For example:

    <AdminList 
         ...
         rowEl={ <RepositoryRow ??? />} />

Is there any way to resolve this?
I’d appreciate any help please.

  • I don’t think I understand your question correctly. However, I think you can pass the element constructor in the props for AdminList instead of the element instance, that way you can pass the props you need from within the component that has access to them. As such: <AdminList rowEl={RepositoryRow} /> and use it inside AdminList as <rowEl /> (you may need to set the name to start with upper case letter since that’s a requirement for React components’ names.)

    – 

you can use one of this ways:

1)Passing data with a render prop :

const AdminList = ( {headerEl, renderRowEl} ) => {
  
  return (
      <div className="admin-container">
          <div className="adminTitle text-center mb-5 fs-3"></div>
          <main>
              { !isLoading && !fetchError && 
                  <div className="col-6 mx-auto">
                      <Table striped bordered hover>
                          {headerEl}
                          <tbody>
                              {showedRepositories.map((repository) => (
                                  {renderRowEl(repository)}
                              ))}
                              ...
  )
}

const App = () => {
  return (
    <AdminList
      headerEl={<RepositoryListHeader />}
      renderRowEl={(repository) => (
        <RepositoryRow
          key={repository.id}
          record={repository}
          formId={newRepositoryFormId}
          handleSave={handleSave}
          handleDelete={handleDelete}
        />
      )}
    />
  );
};

2)render props as ReactComponent:

  const AdminList = ( {headerEl, rowEl} ) => {
      const HeaderEl = headerEl
      const RowEl = rowEl
      return (
          <div className="admin-container">
              <div className="adminTitle text-center mb-5 fs-3"></div>
              <main>
                  { !isLoading && !fetchError && 
                      <div className="col-6 mx-auto">
                          <Table striped bordered hover>
                              <HeaderEl />
                              <tbody>
                                  {showedRepositories.map((repository) => (
                                      <RowEl
                                        key={ repository.id }
                                        record={repository}
                                        formId={newRepositoryFormId}
                                        handleSave={handleSave}
                                        handleDelete={handleDelete}
                                      />
                                  ))}
                                  ...
      )
    }

    const App = () => {
      return (
        <AdminList
          headerEl= { RepositoryListHeader }
          renderRowEl= { RepositoryRow }
        />
      );
    };

Leave a Comment