React table column not displaying data - javascript

I am using React Table and I am trying to make my table clickable to link to a page different for reach row. but now that i have no error screen my column isn't displaying any data for any of the rows.
(when i take away the
Cell: (props) =>
linkTo(`ticket/[id]`, props.ticket_title, `ticket/${props.ticket_id}`),
everything goes back to normal)
this is my column file:
import { linkTo } from '../utils/linkTo';
import { tableFormatted } from '../utils/tableFormatted';
export const TICKET_COLUMNS = [
{
Header: 'Ticket Number',
accessor: 'ticket_id',
},
{
Header: 'Title',
accessor: (d) => `${d.ticket_title} ${d.ticket_id}`,
Cell: (props) =>
linkTo(`ticket/[id]`, props.ticket_title, `ticket/${props.ticket_id}`),
},
{
Header: 'Description',
accessor: 'ticket_text',
},
{
Header: 'Priority',
accessor: 'ticket_priority',
Cell: (props) => tableFormatted(props.value),
},
{
Header: 'Status',
accessor: 'ticket_status',
Cell: (props) => tableFormatted(props.value),
},
{
Header: 'Type',
accessor: 'ticket_type',
Cell: (props) => tableFormatted(props.value),
},
];
This is my linkTo function that i use to try an make the cell clickable:
import { Link } from '#chakra-ui/layout';
import NextLink from 'next/link';
export const linkTo = (
linkInput: string,
children: string,
asInput?: string
) => {
if (asInput) {
return (
<>
<NextLink href={linkInput} as={asInput}>
<Link>{children}</Link>
</NextLink>
</>
);
} else {
return (
<>
<NextLink href={linkInput}>
<td>{children}</td>
</NextLink>
</>
);
}
};
This is the table itself, though i don't think the table is the problem, but who knows, certainly not me haha.:
import React, { useMemo } from 'react';
import { Table } from 'react-bootstrap';
import { Column, useGlobalFilter, useTable } from 'react-table';
import { GlobalFilter } from './GlobalFilter';
type TestTableProps = {
dataInput: any[];
columnInput: any[];
userInput?: any;
};
export const TestTable: React.FC<TestTableProps> = ({
dataInput,
columnInput,
userInput,
}) => {
const meData = userInput ? userInput : null;
const isData = dataInput ? dataInput : [{}];
const columns = useMemo<Column<object>[]>(() => columnInput, []);
const data = useMemo(() => isData, [isData]);
const {
getTableProps,
getTableBodyProps,
headerGroups,
rows,
prepareRow,
state,
setGlobalFilter,
} = useTable(
{
columns,
data,
},
useGlobalFilter
);
const { globalFilter } = state;
if (!isData) {
return <>no data</>;
} else {
return (
<>
<GlobalFilter filter={globalFilter} setFilter={setGlobalFilter} />
<Table
{...getTableProps()}
striped
bordered
hover
responsive
variant="dark"
>
<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>
</>
);
}
};

Related

How can I make react-table v7 multisort on two columns

I'm using react-table v7.8.0 to create a table with 4 columns. I'd like the the table to be sorted by columns date and views. My problem is that the table is only being sorted by the date column.
I have some pagination and manual sorting that appears to be working as expected. I think I've followed the documentation and I'm unsure where my mistake is.
The data is configured in the following file before being passed to a table component:
ViewsPageDayTable.js:
const postDateTemplate = { year: "numeric", month: "short", day: "numeric" }
import Link from "#/components/Link"
import { useMemo } from "react"
import siteMetadata from "#/data/siteMetadata"
import Table from "#/components/homeBrewAnalytics/table"
import LocationCountItem from "#/components/homeBrewAnalytics/locationCountItem"
export default function ViewsPageDayTable({ data }) {
const parsedData = []
for (var i = 0; i < data.length; i++) {
const dataRow = {}
for (var j in data[i]) {
if (j === "date") {
var date = new Date(data[i][j])
dataRow["date"] = date.toLocaleDateString(siteMetadata.locale, postDateTemplate)
} else if (j === "page") {
dataRow["page"] = data[i][j]
} else if (j === "country_count") {
var value = 0
if (data[i][j] == null) {
value = "unknown"
dataRow["country_count"] = null
} else {
value = data[i][j]
value = value.replaceAll("(", "[").replaceAll(")", "]").replaceAll("'", '"')
value = JSON.parse(value)
dataRow["country_count"] = value
}
} else if (j === "views") {
dataRow["views"] = parseInt(data[i][j])
}
}
parsedData.push(dataRow)
}
const PageCellProcessor = ({ value, row: { index }, column: { id } }) => {
return (
<Link href={value} className="hover:underline">
{" "}
{value}{" "}
</Link>
)
}
const LocationCellProcessor = ({ value }) => {
if (value == null) return <div></div>
const result = []
for (var z = 0; z < value.length; z++) {
result.push(<LocationCountItem value={value[z]} />)
}
return (
<div key={value} className="flex flex-shrink">
{result}{" "}
</div>
)
}
const columns = useMemo(
() => [
{
Header: "Date",
accessor: "date",
sortType: (a, b) => {
return new Date(b) - new Date(a)
},
},
{
Header: "Page",
accessor: "page",
Cell: PageCellProcessor,
},
{
Header: "Views",
accessor: "views",
sortType: 'basic',
},
{
Header: "Location",
accessor: "country_count",
Cell: LocationCellProcessor,
},
],
[]
)
return (
<div
id="viewsPerPagePerDay"
className="min-h-32 col-span-3 border-separate border-2 border-slate-800 p-3"
>
<Table columns={columns} data={parsedData} />
</div>
)
}
Table.js:
import { React, useMemo } from "react"
import { useTable, useFilters, useSortBy, usePagination } from "react-table"
import { useState } from "react"
export default function Table({ columns, data, isPaginated = true }) {
const [filterInput, setFilterInput] = useState("")
const handleFilterChange = (e) => {
const value = e.target.value || undefined
setFilter("page", value)
setFilterInput(value)
}
const {
getTableProps,
getTableBodyProps,
headerGroups,
page,
prepareRow,
setFilter,
canPreviousPage,
canNextPage,
pageOptions,
nextPage,
previousPage,
state: { pageIndex, pageSize },
} = useTable(
{
columns,
data,
initialState: {
defaultCanSort: true,
disableSortBy: false,
manualSortBy: true,
sortBy: useMemo(
() => [
{
id: "date",
desc: false,
},
{
id: "views",
desc: true,
},
],
[]
),
pageIndex: 0,
pageSize: 15,
manualPagination: true,
},
},
useFilters,
useSortBy,
usePagination
)
return (
<>
<div className="flex justify-between align-middle">
<div> Page Views</div>
<input
className="mr-0 rounded-sm border border-gray-700 dark:border-gray-500 "
value={filterInput}
onChange={handleFilterChange}
placeholder={" Page name filter"}
/>
</div>
<table {...getTableProps()}>
<thead>
{headerGroups.map((headerGroup) => (
<tr {...headerGroup.getHeaderGroupProps()}>
{headerGroup.headers.map((column) => (
<th
{...column.getHeaderProps(column.getSortByToggleProps())}
className={
column.isSorted ? (column.isSortedDesc ? "sort-desc" : "sort-asc") : ""
}
>
{column.render("Header")}
</th>
))}
</tr>
))}
</thead>
<tbody {...getTableBodyProps()}>
{page.map((row, _) => {
prepareRow(row)
return (
<tr {...row.getRowProps()}>
{row.cells.map((cell) => {
return <td {...cell.getCellProps()}>{cell.render("Cell")}</td>
})}
</tr>
)
})}
</tbody>
</table>
{Boolean(isPaginated) && (
<div id="pagination">
<div id="pageNum">
page {pageIndex + 1} of {pageOptions.length}
</div>{" "}
<div id="nextPrevButtons">
{canPreviousPage ? (
<div id="backButton" onClick={() => previousPage()}>
Previous
</div>
) : null}
{canNextPage ? (
<div id="nextButton" onClick={() => nextPage()}>
Next{" "}
</div>
) : null}
</div>
</div>
)}
</>
)
}

REACT TABLE- Hide rows in table & reset button to display hidden rows

In my column Show there is a switch button (Toggle doesn't seems working in sandbox, maybe because of tailwindcss? but it works in local...) when you click on it, it will turn the selected row into gray (as if the row is disabled but you can still view the content).
We may have also the possibility to switch again and the original row (without gray) appears.
The VisibilityIcon button above the table will remove from all the table the gray/disabled rows (not working either). And a VisibilityoffIcon button that resets all (we get the original table).
Here what I have done but when I click on the Toggle I get errors and all the table is hidden:
export default function MenuDisplay() {
const { menuId } = useParams();
const { match } = JsonRules;
const dataFindings = match.find((el) => el._id_menu === menuId)?._ids ?? [];
const [disabled, setDisabled] = useState(false);
const toggler_disabled = () => {
disabled ? setDisabled(false) : setDisabled(true);
};
const data = useMemo(
() => [
//some headers ....
{
Header: 'Show',
accessor: (row) =>
<Toggle onClick ={toggler_disabled} value={disabled} onChange=
{setDisabled} />
}
],[]
);
...
return (
{
disabled?
<Table
data = { dataFindings }
columns = { data }
/>
: null
}
);
}
You're using useMemo under row data that memoize all rows which have the same click event without dependencies. If you want to call useMemo with an updated state, you can implement it this way
//`show` is your state
//`data` is your rows
useMemo(() => data, [show])
And the second problem is you track the show state which is only a true/false value. If you want to have multiple row states, you need to keep it as an array.
Here is the full code with some explanation (You also can check this playground)
import Table from "./Table";
import React, { useState, useMemo } from "react";
import JsonData from "./match.json";
import { useParams } from "react-router-dom";
import { Link } from "react-router-dom";
import VisibilityOffIcon from "#mui/icons-material/VisibilityOff";
import VisibilityIcon from "#mui/icons-material/Visibility";
export default function MenuDisplay() {
const { menuId } = useParams();
const { match } = JsonData;
const [hiddenRows, setHiddenRows] = useState([]);
const matchData = match.find((el) => el._id_menu === menuId)?._ids ?? [];
//update hidden row list
const updateHiddenRows = (rowId) => {
if (hiddenRows.includes(rowId)) {
//remove the current clicked row from the hidden row list
setHiddenRows(hiddenRows.filter((row) => row !== rowId));
} else {
//add the current clicked row from the hidden row list
setHiddenRows([...hiddenRows, rowId]);
}
};
const data = useMemo(() => [
{
Header: "Name",
accessor: (row) =>
//check current row is in hidden rows or not
!hiddenRows.includes(row._id) && (
<Link to={{ pathname: `/menu/${menuId}/${row._id}` }}>
{row.name}
</Link>
)
},
{
Header: "Description",
//check current row is in hidden rows or not
accessor: (row) => !hiddenRows.includes(row._id) && row.description
},
{
Header: "Dishes",
//check current row is in hidden rows or not
accessor: (row) => !hiddenRows.includes(row._id) && row.dishes,
Cell: ({ value }) => value && Object.values(value[0]).join(", ")
},
{
Header: "Show",
accessor: (row) => (
<button onClick={() => updateHiddenRows(row._id)}>
{!hiddenRows.includes(row._id) ? (
<VisibilityIcon>Show</VisibilityIcon>
) : (
<VisibilityOffIcon>Show</VisibilityOffIcon>
)}
</button>
)
}
], [hiddenRows]);
const initialState = {
sortBy: [
{ desc: false, id: "id" },
{ desc: false, id: "description" },
{ desc: false, id: "dishes" }
]
};
return (
<div>
<Table
data={matchData}
columns={data}
initialState={initialState}
withCellBorder
withRowBorder
withSorting
withPagination
/>
</div>
);
}
Keep a map of item ids that are selected and toggle these values via the Toggle component.
Use separate state for the toggle button to filter the selected items.
Implement a row props getter.
Example:
MenuDisplay
function MenuDisplay() {
const { menuId } = useParams();
const { match } = JsonData;
// toggle show/hide button
const [hideSelected, setHideSelected] = useState(false);
// select rows by item id
const [selected, setSelected] = useState({});
const rowSelectHandler = (id) => (checked) => {
setSelected((selected) => ({
...selected,
[id]: checked
}));
};
const toggleShow = () => setHideSelected((hide) => !hide);
const matchData = (
match.find((el) => el._id_menu === menuId)?._ids ?? []
).filter(({ _id }) => {
if (hideSelected) {
return !selected[_id];
}
return true;
});
const getRowProps = (row) => {
return {
style: {
backgroundColor: selected[row.values.id] ? "lightgrey" : "white"
}
};
};
const data = [
{
// add item id to row data
Header: "id",
accessor: (row) => row._id
},
{
Header: "Name",
accessor: (row) => (
<Link to={{ pathname: `/menu/${menuId}/${row._id}` }}>{row.name}</Link>
)
},
{
Header: "Description",
accessor: (row) => row.description
},
{
Header: "Dishes",
accessor: (row) => row.dishes,
id: "dishes",
Cell: ({ value }) => value && Object.values(value[0]).join(", ")
},
{
Header: "Show",
accessor: (row) => (
<Toggle
value={selected[row._id]}
onChange={rowSelectHandler(row._id)}
/>
)
}
];
const initialState = {
sortBy: [
{ desc: false, id: "id" },
{ desc: false, id: "description" }
],
hiddenColumns: ["dishes", "id"] // <-- hide id column too
};
return (
<div>
<button type="button" onClick={toggleShow}>
{hideSelected ? <VisibilityOffIcon /> : <VisibilityIcon />}
</button>
<Table
data={matchData}
columns={data}
initialState={initialState}
withCellBorder
withRowBorder
withSorting
withPagination
rowProps={getRowProps} // <-- pass rowProps getter
/>
</div>
);
}
Table
export default function Table({
className,
data,
columns,
initialState,
withCellBorder,
withRowBorder,
withSorting,
withPagination,
withColumnSelect,
rowProps = () => ({}) // <-- destructure row props getter
}) {
...
return (
<div className={className}>
...
<div className="....">
<table className="w-full" {...getTableProps()}>
<thead className="....">
...
</thead>
<tbody {...getTableBodyProps()}>
{(withPagination ? page : rows).map((row) => {
prepareRow(row);
return (
<tr
className={....}
{...row.getRowProps(rowProps(row))} // <-- call row props getter
>
...
</tr>
);
})}
</tbody>
</table>
</div>
</div>
);
}

Antd Design EditableRow not changing buttons from "edit" to "save" and "cancel"

Im using Antd library and i can't seem to find where i have the bug.
This is my EditableTableCell component
import React, {Component} from 'react';
import { Form } from '#ant-design/compatible';
import '#ant-design/compatible/assets/index.css';
import { Input, InputNumber, Select, DatePicker } from "antd";
import moment from "moment";
import {EditableContext} from "./EditableTableRow";
const FormItem = Form.Item;
const Option = Select.Option;
class EditableTableCell extends Component {
getInput = (record, dataIndex, title, getFieldDecorator) => {
switch (this.props.inputType) {
case "number":
return (
<FormItem style={{ margin: 0 }}>
{getFieldDecorator(dataIndex, {
rules: [
{
required: true,
message: `Please Input ${title}!`
}
],
initialValue: record[dataIndex]
})(
<InputNumber formatter={value => value} parser={value => value} />
)}
</FormItem>
);
case "date":
return (
<FormItem style={{ margin: 0 }}>
{getFieldDecorator(dataIndex, {
initialValue: moment(record[dataIndex], this.dateFormat)
})(<DatePicker format={this.dateFormat} />)}
</FormItem>
);
case "select":
return (
<FormItem style={{ margin: 0 }}>
{getFieldDecorator(dataIndex, {
initialValue: record[dataIndex]
})(
<Select style={{ width: 150 }}>
{[...Array(11).keys()]
.filter(x => x > 0)
.map(c => `Product ${c}`)
.map((p, index) => (
<Option value={p} key={index}>
{p}
</Option>
))}
</Select>
)}
</FormItem>
);
default:
return (
<FormItem style={{ margin: 0 }}>
{getFieldDecorator(dataIndex, {
rules: [
{
required: true,
message: `Please Input ${title}!`
}
],
initialValue: record[dataIndex]
})(<Input />)}
</FormItem>
);
}
}
render() {
const { editing, dataIndex, title, inputType, record, index,...restProps} = this.props;
return (
<EditableContext.Consumer>
{form => {
const { getFieldDecorator } = form;
return (
<td {...restProps}>
{editing ?
this.getInput(record, dataIndex, title, getFieldDecorator)
: restProps.children}
</td>
);
}}
</EditableContext.Consumer>
);
}
}
export default EditableTableCell;
This is my EditableTableCell component
import React, {Component} from 'react';
import { Form} from '#ant-design/compatible';
export const EditableContext = React.createContext();
class EditableTableRow extends Component {
render() {
return (
<EditableContext.Provider value={this.props.form}>
<tr {...this.props} />
</EditableContext.Provider>
);
}
}
export default EditableTableRow=Form.create()(EditableTableRow);
This is my ProductsPage component im having bug in
import React, {Component} from 'react';
import {Button, Layout, notification, Popconfirm, Space, Table,Typography} from "antd";
import {Link} from "react-router-dom";
import {Content} from "antd/es/layout/layout";
import EditableTableRow, {EditableContext} from "../components/EditableTableRow";
import EditableTableCell from "../components/EditableTableCell";
import API from "../server-apis/api";
import {employeesDataColumns} from "../tableColumnsData/employeesDataColumns";
import {CheckCircleFilled, InfoCircleFilled} from "#ant-design/icons";
class ProductsPage extends Component {
constructor(props) {
super(props);
this.state = {
data: [],
error: null,
isLoaded: false,
editingKey: "",
errorMessage: "",
}
}
columns = [
...employeesDataColumns,
{
title: "Actions",
dataIndex: "actions",
width: "10%",
render: (text, record) => {
const editable = this.isEditing(record);
return editable ? (
<span>
<EditableContext.Consumer>
{form => (<a onClick={() => this.saveData(form, record.username)} style={{ marginRight: 8 }}>Save</a>)}
</EditableContext.Consumer>
<a onClick={this.cancel}>Cancel</a>
</span>
) : (
<Space size="middle">
<a onClick={() => this.edit(record.username)}>Edit</a>
<Popconfirm title="Are you sure you want to delete this product?"
onConfirm={() => this.remove(record.username)}>
<a style={{color:"red"}}>Delete</a>
</Popconfirm>
</Space>
);
},
}
];
isEditing = (record) => {
return record.username === this.state.editingKey;
};
edit(username) {
this.setState({editingKey:username});
}
cancel = () => {
this.setState({ editingKey: ""});
};
componentDidMount() {
this.setState({ loading: true });
const token="Bearer "+ JSON.parse(localStorage.getItem("token"));
API.get(`users/all`,{ headers: { Authorization: token}})
.then(res => {
// console.log(res.data._embedded.productList);
const employees = res.data._embedded.employeeInfoDtoList;
this.setState({loading: false,data:employees });
})
}
async remove(username) {
const token="Bearer "+ JSON.parse(localStorage.getItem("token"));
API.delete(`/users/${username}`,{ headers: { Authorization: token}})
.then(() => {
let updatedProducts = [...this.state.data].filter(i => i.username !== username);
this.setState({data: updatedProducts});
this.successfullyAdded("Employee is deleted. It wont have any access to the website anymore.")
}).catch(()=>this.errorHappend("Failed to delete"));
}
hasWhiteSpace(s) {
return /\s/g.test(s);
}
saveData(form,username) {
form.validateFields((error, row) => {
if (error) {
return;
}
const newData = [...this.state.data];
const index = newData.findIndex(item => username === item.username);
const item = newData[index];
newData.splice(index, 1, {
...item,
...row
});
const token="Bearer "+ JSON.parse(localStorage.getItem("token"));
const response = API.put(`/users/${username}/update`, row,{ headers: { Authorization: token}})
.then((response) => {
this.setState({ data: newData, editingKey: ""});
this.successfullyAdded("Empolyee info is updated")
})
.catch(error => {
this.setState({ errorMessage: error.message });
this.errorHappend("Failed to save changes.")
console.error('There was an error!', error);
});
});
}
successfullyAdded = (message) => {
notification.info({
message: `Notification`,
description:message,
placement:"bottomRight",
icon: <CheckCircleFilled style={{ color: '#0AC035' }} />
});
};
errorHappend = (error) => {
notification.info({
message: `Notification`,
description:
`There was an error! ${error}`,
placement:"bottomRight",
icon: <InfoCircleFilled style={{ color: '#f53333' }} />
});
};
render() {
const components = {
body: {
row: EditableTableRow,
cell: EditableTableCell
}
};
const columns = this.columns.map(col => {
if (!col.editable) {
return col;
}
return {
...col,
onCell: record => {
const checkInput = index => {
switch (index) {
case "price":
return "number";
default:
return "text";
}
};
return {
record,
// inputType: col.dataIndex === "age" ? "number" : "text",
inputType: checkInput(col.dataIndex),
dataIndex: col.dataIndex,
title: col.title,
editing: this.isEditing(record)
};
}
};
});
const { data, loading } = this.state;
return (
<Layout>
<div>
<Link to="/add-product">
<Button style={{float:"right", background: "#0AC035",marginBottom:"1em", marginTop:"1em" }}
type="primary">New emplyee</Button>
</Link>
</div>
<Content>
<Table components={components} bordered dataSource={data} columns={columns} loading={loading} rowKey={data.username} rowClassName="editable-row"/>
</Content>
</Layout>
);
}
}
export default ProductsPage;
This is the bug I'm having:
enter image description here
And i want to have this result like its shown in Antd docs:
enter image description here
Id really appreciate if you take a look and help me figure out where im wrong
Updated Solution:
I find the issue. In render where you map the columns, you just return the column if it's not an editable column. You can check the code below. I added a check if it's dataIndex === 'actions', then return the following code:
Please Follow the link:
https://react-ts-v3fbst.stackblitz.io
Changes:
1.In columns, i remove the render function from the action object:
{
title: 'Actions',
dataIndex: 'actions',
width: '10%',
},
2. In render function where you map the columns, add the following code before this condition if(!col.editable) {,:
if (col.dataIndex === 'actions') {
return {
...col,
render: (text, record) => {
const editable = this.isEditing(record);
return editable ? (
<span>
<EditableContext.Consumer>
{(form) => (
<a onClick={() => this.saveData(form, record.username)} style={{ marginRight: 8 }}>
Save
</a>
)}
</EditableContext.Consumer>
<a onClick={this.cancel}>Cancel</a>
</span>
) : (
<Space size='middle'>
<a onClick={() => this.edit(record.username)}>Edit</a>
<Popconfirm title='Are you sure you want to delete this product?' onConfirm={() => this.remove(record.username)}>
<a style={{ color: 'red' }}>Delete</a>
</Popconfirm>
</Space>
);
}
};
}
When you click on edit, you set the username as key for that particular row for editing, make sure you have username in each record. I tested this using the following data:
const data = [
{ id: 8, name: 'baun', model: '2022', color: 'black', price: 358, quantity: 3, username: 'brvim' },
{ id: 3, name: 'galileo', model: '20221', color: 'white', price: 427, quantity: 7, username: 'john' }
];
Most important, you should select that attribute as key that is unique in all records. As you are using username, i don't know what is your business logic or data looks like, but technically each record can have same username. So you must select something that would always be unique in your complete data.

react-table with filter and select column in the same table

I'm trying to use react-table 7.5 to have a table with search bar and select by rows features.
I have the code of both search and select row separately, but I can't make it work together.
This is my Table component:
const Table = (...) => {
const [data, setData] = useState(MOCK_DATA);
const columns = useMemo(() => COLUMNS, []);
const defaultColumn = React.useMemo(
() => ({
Filter: ColumnFilter,
}),
[]
);
// table props
let {
getTableProps,
getTableBodyProps,
headerGroups,
footerGroups,
rows,
prepareRow,
setGlobalFilter,
selectedFlatRows,
state: { selectedRowPaths },
} = useTable(
{
columns,
data,
},
useFilters,
(hooks) => {
hooks.visibleColumns.push((columns) => [
{
id: "selection",
Header: ({ getToggleAllRowsSelectedProps }) => (
<Checkbox {...getToggleAllRowsSelectedProps()} />
),
Cell: ({ row }) => <Checkbox {...row.getToggleRowSelectedProps()} />,
},
...columns,
]);
},
useRowSelect,
useGlobalFilter
);
const stateF = state;
const { globalFilter } = stateF;
const backButton = (e) => {
e.preventDefault();
setTable(true);
};
return (
<>
<div
className="Table"
}
>
<GlobalFilter filter={globalFilter} setFilter={setGlobalFilter} />
{isFirstTable ? "next" : "submit"}
</button>
<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>
<pre>
<code>
{JSON.stringify(
{
selectedFlatRows: selectedFlatRows.map((row) => row.original),
},
null,
2
)}
</code>
</pre>
</div>
</>
);
};
So this is the code and the main issue is that the compiler says that state is not defined.
Line 66:18: 'state' is not defined no-undef
I've deleted some extra lines that are not related with the issue, like the parameters Table receives.
This is my first question here so I hope I was clear enough. Thanks!
Using the Global filter(Front-end filter), you can easily manage only it using the selectedRowIds react-table In-build variable.
I have implemented the whole project in This link.
https://codesandbox.io/s/admiring-wood-8rxinu?file=/src/components/DataTable.js:2212-2226
I hope this helps you

React Table displaying no result when I use setFilter

I have a table with a global filter and a setFilter.
The global filter works fine and filters the results except for the customField column that I have as an optional column and may or may not have data.
For the custom fields column, I want to create a separate input that filters only that column but when I type into it all the records just disappear and I get no errors, so I'm not sure what's going on.
I would really appreciate any help, thank you.
Record Table
import React from "react";
import {
useTable,
useFlexLayout,
useFilters,
useGlobalFilter
} from "react-table";
import _ from "lodash";
// noinspection ES6CheckImport
import { useHistory } from "react-router-dom";
import Table from "react-bootstrap/Table";
import { useStateWithLocalStorage } from "../../hooks/useStateWithLocalStorage";
// Define a default UI for filtering
function GlobalFilter({
preGlobalFilteredRows,
globalFilter,
setGlobalFilter
}) {
return (
<span>
<input
value={globalFilter || ""}
onChange={e => {
setGlobalFilter(e.target.value || undefined);
}}
placeholder={" Search By Any Field"}
style={{
fontSize: "2.0rem",
width: "100%"
}}
/>
</span>
);
}
function CustomFieldFilter({ filter, setFilter }) {
return (
<input
value={filter || ""}
onChange={e => {
setFilter("customFields", e.target.value || undefined);
}}
placeholder={`Search Custom Field`}
/>
);
}
export const RecordTable = ({ forms }) => {
//TODO figure out why react-table crashes if forms is not set to data variable below first
const data = forms;
let history = useHistory();
const customFields = JSON.parse(localStorage.getItem("..."));
let customFieldName = "";
if (Array.isArray(customFields) && customFields.length) {
customFieldName = customFields[0].customFieldName;
} else {
customFieldName = "Custom Field";
}
const columns = React.useMemo(
() => [
{
Header: "Form Records",
columns: [
{
Header: "Child First Name",
id: "children",
accessor: values => {
let childNames = [];
_.map(values.children, child => {
childNames.push(child.childName);
});
return childNames.join(", ");
}
},
{
Header: "Time In",
accessor: "timeIn"
},
{
Header: "Time Out",
accessor: "timeOut"
},
{
Header: "Guardian Name",
accessor: "parentName"
},
{
Header: customFieldName,
id: "customFields",
accessor: value => {
const customFields = value.customFields;
if (
Array.isArray(customFields) &&
customFields.length &&
customFields[0].customFieldName === customFieldName
)
return <div>{customFields[0].customFieldValue}</div>;
}
}
]
}
],
[]
);
const defaultColumn = React.useMemo(
() => ({
//Filter: CustomFieldFilter,
minWidth: 20,
maxWidth: 150,
width: 120
}),
[]
);
const openViewDisclaimerPage = rowObject => {
console.log(rowObject.original);
history.push("/viewform", { ...rowObject.original });
};
// Use the state and functions returned from useTable to build your UI
const {
getTableProps,
getTableBodyProps,
headerGroups,
rows,
prepareRow,
state,
preGlobalFilteredRows,
setFilter,
setGlobalFilter
} = useTable(
{
columns,
data,
defaultColumn
},
useFilters,
useGlobalFilter,
useFlexLayout
);
// Render the UI for your table
return (
<div>
<div>Records: {rows.length}</div>
<GlobalFilter
preGlobalFilteredRows={preGlobalFilteredRows}
globalFilter={state.globalFilter}
setGlobalFilter={setGlobalFilter}
/>
<CustomFieldFilter filter={state.filter} setFilter={setFilter} />
<div
style={{
height: 500,
border: "2px solid grey",
borderRadius: "5px",
overflow: "scroll"
}}>
<Table striped bordered hover responsive={"md"} {...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({
onClick: () => openViewDisclaimerPage(row)
})}>
{row.cells.map(cell => {
return (
<td {...cell.getCellProps()}>{cell.render("Cell")}</td>
);
})}
</tr>
);
})}
</tbody>
</Table>
</div>
</div>
);
};
Here is a quick recording of whats happening.

Categories