<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: tjallen27</title>
    <description>The latest articles on DEV Community by tjallen27 (@tjallen27).</description>
    <link>https://dev.to/tjallen27</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F588512%2F4531d666-4c50-4f70-ad2e-ef9c134b1fe5.jpeg</url>
      <title>DEV Community: tjallen27</title>
      <link>https://dev.to/tjallen27</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/tjallen27"/>
    <language>en</language>
    <item>
      <title>How I made a re-usable Table component with TypeScript and React</title>
      <dc:creator>tjallen27</dc:creator>
      <pubDate>Wed, 21 Aug 2024 10:31:48 +0000</pubDate>
      <link>https://dev.to/tjallen27/how-i-made-a-re-usable-table-component-with-typescript-and-react-1dmo</link>
      <guid>https://dev.to/tjallen27/how-i-made-a-re-usable-table-component-with-typescript-and-react-1dmo</guid>
      <description>&lt;p&gt;Trying to build on my very basic TypeScript knowledge, I decided to rebuild a project I built about a year ago using TypeScript. Trying to avoid the urge to put &lt;code&gt;any&lt;/code&gt; everywhere, I've done some learning and made a start by building a component that was used thought my project. The Table. &lt;/p&gt;

&lt;p&gt;In my previous project, I had about 3 separate Table components that were all slightly different and I just shipped it to get something out there. I knew it was horrible but I did it anyway.&lt;/p&gt;

&lt;p&gt;This time, I wanted to build something reusable, type-safe and something I'd be happy showing off. So here it is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from "react";

interface TableProps&amp;lt;T&amp;gt; {
  headers: string[];
  data: T[];
  renderRow: (item: T) =&amp;gt; React.ReactNode;
}

const Table = &amp;lt;T,&amp;gt;({
  headers,
  data,
  renderRow,
}: TableProps&amp;lt;T&amp;gt;): JSX.Element =&amp;gt; {
  return (
    &amp;lt;table&amp;gt;
      &amp;lt;thead&amp;gt;
        &amp;lt;tr&amp;gt;
          {headers.map((header) =&amp;gt; (
            &amp;lt;td key={header}&amp;gt;{header}&amp;lt;/td&amp;gt;
          ))}
        &amp;lt;/tr&amp;gt;
      &amp;lt;/thead&amp;gt;
      &amp;lt;tbody&amp;gt;
        {data.map((item, index) =&amp;gt; (
          &amp;lt;tr key={index}&amp;gt;{renderRow(item)}&amp;lt;/tr&amp;gt;
        ))}
      &amp;lt;/tbody&amp;gt;
    &amp;lt;/table&amp;gt;
  );
};

export default Table;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's break it down. Firstly the interface. This describes the structure of the data used by the table. To make it reusable, the type of data can vary, therefore TypeScript generics need to be used. The data is an array of some type, T, the headers are just an array of strings, and I decided to create a renderRow function so I can pass in anything into the table rows which holds the shape of &lt;code&gt;T&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;TableProps&amp;lt;T&amp;gt;&lt;/code&gt; is like passing an argument into a function. We're saying if I want to use &lt;code&gt;data: T[]&lt;/code&gt;, I need to pass &lt;code&gt;T&lt;/code&gt; into the interface. This will set the type of &lt;code&gt;data&lt;/code&gt; to whatever the type is of the data we are passing in. &lt;/p&gt;

&lt;p&gt;Similarly when defining the Table, we need to say that we are passing a generic type so we need to add &lt;code&gt;&amp;lt;T,&amp;gt;&lt;/code&gt;.  The props are in the shape of TableProps and return a JSX element:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;({
  headers,
  data,
  renderRow,
}: TableProps&amp;lt;T&amp;gt;): JSX.Element =&amp;gt; {...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's basically the TypeScript part of it. This is how it's used:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;Table headers={headers} data={data} renderRow={renderRow} /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With renderRow defining the table rows, e.g.:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const renderRow = (user: User) =&amp;gt; {
  return (
    &amp;lt;&amp;gt;
      &amp;lt;td&amp;gt;{user.name}&amp;lt;/td&amp;gt;
      &amp;lt;td&amp;gt;{user.age}&amp;lt;/td&amp;gt;
      &amp;lt;td&amp;gt;{user.address}&amp;lt;/td&amp;gt;
      &amp;lt;td&amp;gt;{user.email.}&amp;lt;/td&amp;gt;
    &amp;lt;/&amp;gt;
  );
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This way of rendering rows maps over the data we pass it, and create a table row containing the item that is passed into the renderRow function.&lt;/p&gt;

&lt;p&gt;Hope that all makes sense! &lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
