React table - how to merge tables for specific column and cell value
This is 2 tables that I've created.
and it's its data
const callData = [
{ id: 1, type: "call", volume: 50000, strike: 3000 },
{ id: 2, type: "call", volume: 30000, strike: 5000 },
{ id: 3, type: "call", volume: 20000, strike: 7000 }
];
const putData = [
{ id: 1, type: "put", volume: 50000, strike: 3000 },
{ id: 2, type: "put", volume: 10000, strike: 5000 },
{ id: 3, type: "put", volume: 7000, strike: 7000 }
];
If you click the row, it will print something like
const rowOnClick = (row) => {
let obj = row.values;
console.log(`clicked ${obj.type} for Strike ${obj.strike}`);
};
// log "clicked call for Strike 3000"
Now I want to merge these 2 tables together.
The one single table will be like
If I click the row in red box, it should print clicked call for Strike xxx
.
If I click the row in green box, it should print clicked put for Strike xxx
.
For example, if I click the row in red box for strike 5000
, it prints clicked call for Strike 5000
How can I do it?
Codesandbox
https://codesandbox.io/s/vigilant-easley-v6h8p?file=/src/App.js:0-2789
App.js
import React, { useEffect } from "react";
import styled from "styled-components";
import { useTable } from "react-table";
const Styles = styled.div`
padding: 1rem;
table {
border-spacing: 0;
border: 1px solid black;
tr {
:last-child {
td {
border-bottom: 0;
}
}
}
th,
td {
margin: 0;
padding: 0.5rem;
border-bottom: 1px solid black;
border-right: 1px solid black;
:last-child {
border-right: 0;
}
}
}
`;
function Table({ columns, data }) {
// Use the state and functions returned from useTable to build your UI
const {
getTableProps,
getTableBodyProps,
headerGroups,
rows,
prepareRow
} = useTable({
columns,
data
});
const rowOnClick = (row) => {
let obj = row.values;
console.log(`clicked ${obj.type} for Strike ${obj.strike}`);
};
// Render the UI for your table
return (
<table {...getTableProps()}>
<thead>
{headerGroups.map((headerGroup) => (
<tr {...headerGroup.getHeaderGroupProps()} onClick={() => {}}>
{headerGroup.headers.map((column) => (
<th {...column.getHeaderProps()}>{column.render("Header")}</th>
))}
</tr>
))}
</thead>
<tbody {...getTableBodyProps()}>
{rows.map((row, i) => {
prepareRow(row);
return (
<tr
{...row.getRowProps()}
onClick={() => {
rowOnClick(row);
}}
>
{row.cells.map((cell) => {
return <td {...cell.getCellProps()}>{cell.render("Cell")}</td>;
})}
</tr>
);
})}
</tbody>
</table>
);
}
function App() {
const columns = React.useMemo(
() => [
{
Header: "Info",
columns: [
{
Header: "Type",
accessor: "type"
},
{
Header: "Volume",
accessor: "volume"
},
{
Header: "Strike",
accessor: "strike"
}
]
}
],
[]
);
// got below data from async request
const callData = [
{ id: 1, type: "call", volume: 50000, strike: 3000 },
{ id: 2, type: "call", volume: 30000, strike: 5000 },
{ id: 3, type: "call", volume: 20000, strike: 7000 }
];
const putData = [
{ id: 1, type: "put", volume: 50000, strike: 3000 },
{ id: 2, type: "put", volume: 10000, strike: 5000 },
{ id: 3, type: "put", volume: 7000, strike: 7000 }
];
return (
<Styles>
<Table columns={columns} data={callData} />
<Table columns={columns} data={putData} />
</Styles>
);
}
export default App;
You can merge your data into one object and render juse one table. Also instaed of using onClick
on the tr
element, you can handle your requirement by using onClick
on the td
elements and decide what data should be send to rowOnClick
method, on the callback of td
's onClick.like this:
{rows.map((row, i) => {
prepareRow(row);
return (
<tr {...row.getRowProps()}>
{row.cells.map((cell) => {
...
return <td {...cell.getCellProps()}
onClick={ column === 'strike' ? undefined : ()=> rowOnClick({...})}>
{cell.render("Cell")}</td>;
})}
</tr>
);
})}
I implemented an example here on codesandbox you can check it out.