Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React Functional Component Inheritance

i created a React functional component that is a wrapper around the react-data-grid component. now i need a second component that is exactly the same except for one function (the rowGetter if you are familiar with react-data-grid.)

i work on an intranet so i will type a quick example...

function UsersInfoDataTable(props) {

  const userInfoCols = [
    {key: "a", name: "A", ...},
    {key: "b", name" "B", ...},
    {key: "c", name" "C", ...},
    ...
  ];

  const aCellCreation = (aData, description, index) => (
    <span title={...}>...</span>
  )

  const bCellCreation = (bData, index) => (
    <div className={...}>...</div>
  }

  ...

  
  const formattedTableData = props.myData.map(function (obj, index) {
    //do some stuff
    return {"a": aCellCreation(obj.a, obj.desc,index), "b": bCellCreation(obj.b, index), ...}
  });

  const rowGetter = rowNumber => formattedTableData[rowNumber];

  return (
    <div>
      <ReactDataGrid
        columns={userInfoCols}
        rowGetter={rowGetter}
        rowCount={formattedTableData.length}
        minHeight={props.minHeight}
       />
     </div>
   )
}

export default UsersInfoDataTable;

now i need something like this too...

function UsersInfoDataTableSlightlyDifferent(props) {

  //i need the same columns
  const userInfoCols = [
    {key: "a", name: "A", ...},
    {key: "b", name: "B", ...}
  ];

  //i need same cell format    
  const aCellCreation = (aData, description, index) => (
    <span title={...}>...</span>
  )

  //i need same cell format
  const bCellCreation = (bData, index) => (
    <div className={...}>...</div>
  }

  ...

  //the internals of this function will be pretty much the only difference
  const formattedTableData = props.myData.map(function (obj, index) {

    //do some different stuff than previous component as myData will be
    //in a different format when passed here versus the other component

    //the return will be essentially the same - maybe slightly different with
    //what is passed to the "creation" functions
    return {"a": aCellCreation(obj.a, obj.desc,index), "b": bCellCreation(obj.b, index), ...}
  });

  const rowGetter = rowNumber => formattedTableData[rowNumber];

  return (
    <div>
      <ReactDataGrid
        columns={userInfoCols}
        rowGetter={rowGetter}
        rowCount={formattedTableData.length}
        minHeight={500}
       />
     </div>
   )
}

export default UsersInfoDataTable;

A couple ways i thought to do what i want...

  1. Copy and paste with no reuse - bad
  2. Reuse the exact same component but check for data in one prop and if it exists loop and do stuff one way else loop through the other prop and do stuff different
  3. Change to use a React class instead of functional component and use inheritance (which i haven't had to do before so i'd have to do some reading)
  4. Change to use a React class and have all the functions be static and use them the static functions from one component in both components. ie. aCellCreation() and bCellCreation() would be static.

i'm kind of leaning towards #2 but what if i want to have essentially the same table and display user info from 4 different sources - it could get ugly. e.g. dataToMapThrough = props.allUsersData? props.allUserData : (props.usersFromUSAData? props.usersFromUSAData : ...)

Any suggestions on the best way to accomplish this?


UPDATE

Reading the document provided by Andy_D here is what i came up with if anyone is interested. Hopefully no typos since i had to hand type everything since i work on an intranet site...

function UsersInfoDataTableDisplayer(props) {

  const userInfoCols = [
    {key: "a", name: "A", ...},
    {key: "b", name: "B", ...}
  ];

  const aCellCreation = (aData, description, index) => (
    <span title={...}>...</span>
  )

  const bCellCreation = (bData, index) => (
    <div className={...}>...</div>
  }

  ...

  //data will already be processed exactly how this Component needs it every time
  //in the specialized version of this Component
  const formattedTableData = props.userInfoData.map(function (obj, index) {

    //Probably nothing to do here since data is processed in the specialized 
    //version of this component

    return {"a": aCellCreation(obj.a, obj.b,index), "b": bCellCreation(obj.b, index),"c": obj.c}
  });

  const rowGetter = rowNumber => formattedTableData[rowNumber];

  return (
    <div>
      <ReactDataGrid
        columns={userInfoCols}
        rowGetter={rowGetter}
        rowCount={formattedTableData.length}
        minHeight={500}
       />
     </div>
   )
}

export default UsersInfoDataTableDisplayer;

Now here is a specialized version #1...

function UsersInfoFromService1DataTable(props) {

  //The format of the JSON passed in is one way here 
  const formattedTableData = props.abcData.map(function (obj, index) {

    //"combine" and "clean" or whatever you need here
    let aLikeData = obj.firstName + ' ' + obj.lastName

    return {"a": aLikeData, "b": obj.description, "c": obj.whatever,...}
  });



  return (
    <div>
      <UsersInfoDataTableDisplayer
        userInfoData = {formattedTableData}
        minHeight={500}
       />
     </div>
   )
}

export default UsersInfoFromService1DataTable;

Here is specialized version #2...

function UsersInfoFromService1DataTable(props) {

  //The format of the JSON passed in is one way here 
  const formattedTableData = props.xyzData.map(function (obj, index) {

    //"combine" and "clean" or whatever you need here
    let aLikeData = obj.fullName

    return {"a": aLikeData, "b": obj.desc, "c": obj.something,...}
  });



  return (
    <div>
      <UsersInfoDataTableDisplayer
        userInfoData = {formattedTableData}
        minHeight={900}
       />
     </div>
   )
}

export default UsersInfoFromService2DataTable;
like image 500
user2052618 Avatar asked May 31 '17 14:05

user2052618


People also ask

Can you do components inheritance in React?

In React, the composition model is used instead of inheritance, so that code can be re-used again between the components. In react extends keyword is used on the main function i.e the constructor function.

Why composition is better than inheritance in React?

React team suggests using Composition over Inheritance. React treats everything as a component and follows a strong component-based model. This is one of the main reasons why composition is a superior technique for code reuse than inheritance.

What is composition and inheritance React?

Composition and inheritance are the approaches to use multiple components together in React. js . This helps in code reuse. React recommend using composition instead of inheritance as much as possible and inheritance should be used in very specific cases only.


1 Answers

The React docs address this question here: https://facebook.github.io/react/docs/composition-vs-inheritance.html

I'd read that and, within those guidelines, do whatever seems best.

TL;DR - don't use inheritance. But please do read.

like image 67
Andy_D Avatar answered Sep 21 '22 09:09

Andy_D