I'm new to Javascript so please bear with me. I'm attempting to render a table of data inside a div and I'm unable to do so. Basically I just want to replace the div in the html with the table div we've created.
I'm using react table v7 with webpack. The following code results in this being seen in the browser where the table should be.
Here is my code:
import { useTable } from 'react-table';
const ReactTable = require('react-table');
import React from 'react';
const tableData = [
{someColumn: 1, someOtherColumn: 'A'},
{someColumn: 2, someOtherColumn: 'B'}
]
const columnGenerator = (columnNames) => {
var updatedNames = columnNames.map(c => {
return {
Header: camelToTitle(c),
accessor: c
}
});
return [
{
Header: "Claims Data",
columns: updatedNames
},
]
};
const Table = ({ columns, data }) => {
const {
getTableProps,
getTableBodyProps,
headerGroups,
rows,
prepareRow
} = useTable({
columns,
data
});
return (
<table {...getTableProps()}>
<thead>
{headerGroups.map(headerGroup => (
<tr {...headerGroup.getHeaderGroupProps()}>
{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()}>
{row.cells.map(cell => {
return <td {...cell.getCellProps()}>{cell.render("Cell")}</td>;
})}
</tr>
);
})}
</tbody>
</table>
);
};
const table = <div>
<Table
columns={columnGenerator(Object.keys(tableData[0]))}
data={tableData}
/>
</div>
document.getElementById('claim-table').append(table);
[object Object] is just what is being rendered by converting that table object into a String. I would start by trying to use ReactDOM to mount that node instead of append:
import ReactDOM from 'react-dom'
...
ReactDOM.render(<Table
columns={columnGenerator(Object.keys(tableData[0]))}
data={tableData}
/>,
document.getElementById('claim-table')
)
Related
i'm new to reactjs and i'm trying to make a table that shows the information from a array of objects and have a button of delete and an input to search among the users. The delete button is working correctly when i'm not searching anything, but when i'm searching it doesn't delete the corretly row, and deletes only the first one. I see that it is because the arrays that show the table are different with and without the search being used but I don't know how to make it work.
this is the component of the table:
import { formatDate } from "../../utils/formatDate";
import "./table.css";
import { useState } from "react";
function Table(props) {
const { headerData, bodyData, type, removeItem} = props;
const isUser = type === "user";
const buildTableItems = () => {
return bodyData.map((item, index) => (
<tr className="data-tr">
<td>{item.name}</td>
<td>{item.email}</td>
<td>{item.occupation}</td>
<td>{formatDate(item.birthday)}</td>
<td>
<button className="delete-button" onClick={() => removeItem(index)}>
Delete
</button>
</td>
</tr>
));
};
return (
<div className="user-data">
<table className="user-table">
<thead>
<tr className="data-th">
{headerData.map((headerTable) => (
<th >{headerTable}</th>
))}
</tr>
</thead>
<tbody>{buildTableItems()}</tbody>
</table>
</div>
);
}
export default Table;
Here the component of the search bar:
import "./searchBar.css"
function SearchBar({ searchedData, onSearch }) {
return (
<div className="search-bar">
<label>Search</label>
<input type="text" placeholder="Search User" value={searchedData} onChange={e => onSearch(e.target.value)} />
</div>
);
}
export default SearchBar;
and here is the home:
import "./Home.css";
import React, { useEffect, useState } from "react";
import Header from "../components/Header/Header";
import Table from "../components/Table/Table";
import AddData from "../components/AddData/AddData";
import SearchBar from "../components/SearchBar/SearchBar";
import { userArr } from "../mock/users";
const Home = () => {
const headerUser = ["Name", "Email", "Occupation", "Birthday"];
const [newUserArr, setNewUserArr] = useState(userArr);
const [searchedItem, setSearchedItem] = useState("");
const searchedArray = newUserArr.filter((item) => {
if (item.name.toLowerCase().includes(searchedItem.toLowerCase())) {
return true;
}
});
function onSearch(e) {
setSearchedItem(e);
}
const addDataToArr = (form) => {
setNewUserArr([...newUserArr, form]);
};
const deleteData = (indexUserArr) => {
let restOfDataArray = newUserArr.filter(
(element, ind) => ind !== indexUserArr
);
setNewUserArr(restOfDataArray);
};
return (
<>
<Header />
<SearchBar searchedData={searchedItem} onSearch={onSearch} />
<Table
type="user"
headerData={headerUser}
bodyData={newUserArr}
removeItem={(index) => deleteData(index)}
/>
<AddData saveData={(val) => addDataToArr(val)} />
</>
);
};
export default Home;
thank you
If you have ID in your user data then use that instead of index or create id keywords using concatenate with your values here is examples.
import { formatDate } from "../../utils/formatDate";
import "./table.css";
import { useState } from "react";
function Table(props) {
const { headerData, bodyData, type, removeItem} = props;
const isUser = type === "user";
const buildTableItems = () => {
return bodyData.map((item, index) => (
<tr className="data-tr">
<td>{item.name}</td>
<td>{item.email}</td>
<td>{item.occupation}</td>
<td>{formatDate(item.birthday)}</td>
<td>
<button className="delete-button" onClick={() => removeItem(`${item.name}${item.email}${item.occupation}`)}>
Delete
</button>
</td>
</tr>
));
};
return (
<div className="user-data">
<table className="user-table">
<thead>
<tr className="data-th">
{headerData.map((headerTable) => (
<th >{headerTable}</th>
))}
</tr>
</thead>
<tbody>{buildTableItems()}</tbody>
</table>
</div>
);
}
export default Table;
And here is your delete method ${item.name}${item.email}${index}
const deleteData = (data) => {
let restOfDataArray = newUserArr.filter(
(element, ind) => `${element.name}${element.email}${element.occupation}` !== data
);
setNewUserArr(restOfDataArray);
};
This will fixed your problem. If this doesn't work then you need to use ID to resolve this problem. There is a possibility that ${item.name}${item.email}${item.occupation} can be duplicates.
Never use index ever for deleting or any other operations. Use always ID.
I have a issue trying to fill a table with data that i recieve from a api.
I used axios to get the information, then i stored that into a state, and finally, i send to a projectsTable, that's a component to render a table with all the data.
The message that i recieved from the console is the follow "Uncaught Error: Objects are not valid as a React child (found: object with keys {---}). If you meant to render a collection of children, use an array instead."
I put some console logs to try to find the problem, and i saw that in the useEffect (when i read the information first), the setState doesn't execute.
I think that the problem could be in the render, because it's try to return the ProjectTable BEFORE the setProjects is execute, am i right?
Here I detach the code
export default function App() {
const columns = useMemo(
() => [
{
Header: 'Project',
columns: [
{
Header: 'Name',
accessor: 'name'
},
{
Header: 'details',
accessor: 'details'
}
]
}
const [projects, setProjects] = useState([]);
useEffect(() => {
axios
.get(URL_PROJECTS)
.then((response) => {
setProjects(response.data);
})
.catch((err) => console.log(err));
}, []);
return (
<div>
{projects.length !== 0 ? <ProjectTable data={projects} columns={columns} /> : <div />}
</div>
);
ProjectTable
export default function ProjectTable({ data, columns }) {
const { getTableProps, getTableBodyProps, headerGroups, rows, prepareRow } = useTable({
columns,
data
});
return (
<table {...getTableProps()}>
<thead>
{headerGroups.map((headerGroup) => (
<tr {...headerGroup.getHeaderGroupProps()}>
{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()}>
{row.cells.map((cell) => (
<td {...cell.getCellProps()}>{cell.render('Cell')}</td>
))}
</tr>
);
})}
</tbody>
</table>
);
}
I am quite new to development and just started with react. I have implemented a react-table and when rendered it in the App.js file but then I open the browser it does not render anything and gives an error in the consoleThis is the snapshot of the error
I also tried the Error Boundry method to see if it helps but it didn't
BasicTable.js
import { useTable } from "react-table";
import Mockdata from "./Mockdata.json";
import { Columns } from "./Columns";
export const BasicTable = () => {
const columns = useMemo(() => Columns,[]);
const data = useMemo(() => Mockdata,[]);
const tableInstance = useTable({ columns, data });
const { getTableProps, getTableBodyProps, headerGroups, rows, prepareRow } =
tableInstance;
return (
<table {...getTableProps()}>
<thead>
{headerGroups.map((headerGroup) => (
<tr {...headerGroup.getHeaderGroupProps()}>
{headerGroup.headers.map((column) => (
<th {...column.getHeaderProps()}>{column.render('Header')}</th>
))}
</tr>
))}
</thead>
<tbody {...getTableBodyProps()}>
{rows.map((row) => {
prepareRow(row);
return (
<tr {...row.getRowProps()}>
{row.cells.map((cell) => {
return <td {...cell.getCellProps()}>{cell.render('cell')}</td>;
})}
</tr>
);
})}
</tbody>
</table>
);
};
------------------------------------------------------
Mockdata.json
[
{
"id":"1a",
"name":"Prop1",
"defaultValue":"P1"
},
{
"id":"2a",
"name":"Prop2",
"defaultValue":"P2"
},
{
"id":"3a",
"name":"Prop3",
"defaultValue":"P3"
}
]
------------------------------------------------------------
Columns.js
export const Columns = [
{
Header:'Id',
accessor: 'id'
},
{
Header:'Name',
accessor: 'name'
},
{
Header:'DefaultValue',
accessor: 'defaultValue'
}
]
---------------------------------------------------------
App.js
import React from 'react';
import './App.css';
import { BasicTable } from './components/BasicTable';
function App() {
return (
<div className="App">
<BasicTable></BasicTable>
</div>
);
}
export default App;
include the Cell as capital c in which u rendered small c in return
that might help
[Link to Codesandbox of react-table
By default it will show all the available columns and when selecting 2 dropdown values it should show the 2 columns for comparison. So therefore it should display it in react table. I see there is an example of ticking checkboxes to show which column will be hidden, but in my case I want other way around when I have show the 2 columns when both dropdown is selected before showing it.
import { FC, useState } from "react";
import { useTable } from "react-table";
interface Column {
Header: string;
accessor: string;
id: Function | string | number;
}
interface TableProps {
columns: Array<any>;
data: Array<any>;
}
export const Table: FC<TableProps> = ({ columns, data }) => {
const {
getTableProps,
getTableBodyProps,
headerGroups,
rows,
prepareRow,
allColumns,
} = useTable({
data,
columns,
});
const [valueOne, setValueOne] = useState("");
const [valueTwo, setValueTwo] = useState("");
const handleChangeOne = (e: any) => setValueOne(e.target.value);
const handleChangeTwo = (e: any) => setValueTwo(e.target.value);
return (
<>
<select value={valueOne} onChange={handleChangeOne}>
{allColumns.map((column) => (
<option value={column.id} {...column.getToggleHiddenProps()}>
{column.id}
</option>
))}
</select>
<select value={valueTwo} onChange={handleChangeTwo}>
{allColumns.map((column) => (
<option value={column.id} {...column.getToggleHiddenProps()}>
{column.id}
</option>
))}
</select>
<table {...getTableProps()}>
<thead>
{headerGroups.map((headerGroup) => (
<tr {...headerGroup.getHeaderGroupProps()}>
{headerGroup.headers.map((column) => (
<th {...column.getHeaderProps()}>{column.render("Header")}</th>
))}
</tr>
))}
</thead>
<tbody {...getTableBodyProps()}>
{rows.map((row) => {
prepareRow(row);
return (
<tr {...row.getRowProps()}>
{row.cells.map((cell) => (
<td {...cell.getCellProps()}>{cell.render("Cell")}</td>
))}
</tr>
);
})}
</tbody>
</table>
</>
);
};
I would just use somthing like headerGroup.headers.filter((i)=> i === valueOne || i === valueTwo ).map(.....
I am new to react. I have a json api which I need to display as a table in client side. I want to use react-table v7. My idea is:
Take the keys from the data as column Headers and Accessor
The json data are the rows
I have a table component, it takes the headers and data as props, kindly look below:
import React from 'react';
import { useTable } from 'react-table'
const Table = ({
headers,
items
}) => {
function getColumns() {
if (headers) {
return headers.map(key => {
return {
Header: key.toString(),
accessor: key.toString()
};
});
}}
const columns = React.useMemo(() => [
getColumns()
],
[]
)
const data = React.useMemo(() => [
items
], []
)
const {
getTableProps,
getTableBodyProps,
headerGroups,
rows,
prepareRow,
} = useTable({ columns, data })
return (
<table {...getTableProps()} style={{ border: 'solid 1px blue' }}>
<thead>
{headerGroups.map(headerGroup => (
<tr {...headerGroup.getHeaderGroupProps()}>
{headerGroup.headers.map(column => (
<th
{...column.getHeaderProps()}
style={{
borderBottom: 'solid 3px red',
background: 'aliceblue',
color: 'black',
fontWeight: 'bold',
}}
>
{column.render('Header')}
</th>
))}
</tr>
))}
</thead>
<tbody {...getTableBodyProps()}>
{rows.map(row => {
prepareRow(row)
return (
<tr {...row.getRowProps()}>
{row.cells.map(cell => {
return (
<td
{...cell.getCellProps()}
style={{
padding: '10px',
border: 'solid 1px gray',
background: 'papayawhip',
}}
>
{cell.render('Cell')}
</td>
)
})}
</tr>
)
})}
</tbody>
</table>
)
}
export default Table;
Then I have another component to make get request via axios and set columns and data from its response and import the Table component to pass the props define here, code below:
import React, { useEffect, useState } from 'react'
import Table from './Table'
import axios from 'axios'
export const STable = () => {
const [columns, setColumns] = useState([])
const [rows, setRows] = useState([])
const getData = () => {
axios.get("http://localhost:5001/")
.then(res => {
console.log(res.data)
setColumns({ columns: Object.keys(res.data[0]) })
setRows({ rows: res.data })
})
.catch(error => {
console.log(error)
})
}
useEffect(() => {
getData()
}, [] )
return (
<div>
<Table headers={columns} items={rows} />
</div>
)
}
export default Stable;
Finally the App component
import React from 'react';
import STable from './components/STable';
function App() {
return (
<div>
<STable/>
</div>
);
}
export default App;
However I get this error, see pic,
I do not know where I am doing wrong. I would appreciate any help.
You need to have id field in all columns with accessors. In your code you need to set id field for every inner column like that.
return headers.map(key => {
return {
id: key toString(),
Header: key.toString(),
accessor: key.toString()
};
});