ReactTable - react component with REST API Call - javascript

Can you please suggest me how to update the data in the grid. I am updating the data on the server request. How do re-render the data table? In the render section, I have used react Table component. Can you please suggest me the actual approach to use this react table component>
import React, { PureComponent } from 'react';
import ReactTable from 'react-table'
import "./Vendors.css";
export default class VendorsList extends PureComponent {
data = [{
name: 'Tanner Linsley',
age: 26,
friend: {
name: 'Jason Maurer',
age: 23
}
}];
columns = [{
Header: 'Name',
accessor: 'name' // String-based value accessors!
}, {
Header: 'Age',
accessor: 'age',
Cell: props => <span className='number'>{props.value}</span> // Custom cell components!
}, {
id: 'friendName', // Required because our accessor is not a string
Header: 'Friend Name',
accessor: d => d.friend.name // Custom value accessors!
}, {
Header: props => <span>Friend Age</span>, // Custom header components!
accessor: 'friend.age'
}];
constructor(props) {
super(props);
fetch("http://api.com/vendor/list", {
method : 'POST'
})
.then(res => res.json())
.then(
(result) => {
this.data = [{
name: 'Tanner Linsley',
age: 290,
friend: {
name: 'Maurer',
age: 23
}
}];
}
)
}
render() {
return
<div>
<div className="gridsize"><ReactTable data={this.data} columns={this.columns} /></div>
</div>
}
}
Raja

you need to use states..
and call setState when you get response from your server. calling the setState function will call render function automatically

When you want to update the view based on a change in data, you should store the data in state and update it using setState which will trigger a re-render and update the view. Also API request must be handled in componentDidMount lifecycle function and not constructor
export default class VendorsList extends PureComponent {
state = {
data = [{
name: 'Tanner Linsley',
age: 26,
friend: {
name: 'Jason Maurer',
age: 23
}
}];
}
columns = [{
Header: 'Name',
accessor: 'name' // String-based value accessors!
}, {
Header: 'Age',
accessor: 'age',
Cell: props => <span className='number'>{props.value}</span> // Custom cell components!
}, {
id: 'friendName', // Required because our accessor is not a string
Header: 'Friend Name',
accessor: d => d.friend.name // Custom value accessors!
}, {
Header: props => <span>Friend Age</span>, // Custom header components!
accessor: 'friend.age'
}];
componentDidMount() {
fetch("http://api.com/vendor/list", {
method : 'POST'
})
.then(res => res.json())
.then((result) => {
this.setState({data: [{
name: 'Tanner Linsley',
age: 290,
friend: {
name: 'Maurer',
age: 23
}
}]
});
)};
}
render() {
return (
<div>
<div className="gridsize"><ReactTable data={this.state.data} columns={this.columns} /></div>
</div>
)
}
}

Related

How can I use data that isn't displayed in a row in React-Table?

For example, I would like to use id as something that would be passed in the Actions header located in the Actions Component via row.values. While I can get the values for first and last name, I cannot for id
const Accounts = () => {
const [columns,setColumns] = useState(useMemo(() => [
{
Header: 'First Name',
accessor: 'firstName',
},
{
Header: 'Last Name',
accessor: 'lastName',
},
{
Header: 'Actions',
Cell: ({row}) => (
<Actions values={row.values}/>
)
}
],
[]
));
const [data,setData] = useState(useMemo(() => [
{
id:1,
firstName:"john",
lastName:"johnson",
},
{
id:2,
firstName:"dave",
lastName:"jones",
},
{
id:3,
firstName:"steve",
lastName:"smith",
},
], []));
return (
<>
// react-table component
<Table columns={columns} data={rdata}/>
</>
)
}
You can access all your row data using row.original

How to reset ant design table selected rows?

I am using ant design table component and I have selected rows.
I want onClick reset selected rows.
I can not find out where it stores selected rows.
const rowSelection = {
onChange: (selectedRowKeys, rows) => {
this.setState({
selectedRowsArray: [...rows]
});
},
};
<Table rowSelection={rowSelection} columns={columns} dataSource={paymentsHistory} />
Any Idea how to clear selected rows?
rowSelection also takes selectedRowKeys property that will help you control the selected rows at any point in time.
const { selectedRowsArray } = this.state;
const rowSelection = {
selectedRowKeys: selectedRowsArray,
onChange: (selectedRowKeys, rows) => {
this.setState({
selectedRowsArray: [...rows]
});
},
};
<Table rowSelection={rowSelection} columns={columns} dataSource={paymentsHistory} />
Codesandbox Example | Antd Docs
We can also do this with hooks:
import { useState } from 'react';
import { Table, Button } from 'antd';
function App() {
const [selectedRowKeys, setRowKeys] = useState([]);
const [loading, setLoading] = useState([]);
const start = () => {
setRowKeys([]);
};
const onSelectChange = selectedRowKeys => {
setRowKeys(selectedRowKeys);
};
const rowSelection = {
selectedRowKeys,
onChange: onSelectChange,
};
const dataSource = [
{
key: '1',
name: 'Mike',
age: 32,
address: '10 Downing Street',
},
{
key: '2',
name: 'John',
age: 42,
address: '10 Downing Street',
}, enter code here
];
const columns = [
{
title: 'Name',
dataIndex: 'name',
key: 'name',
},
{
title: 'Age',
dataIndex: 'age',
key: 'age',
},
{
title: 'Address',
dataIndex: 'address',
key: 'address',
},
];
return (
<div className="App">
<Button type="primary" onClick={start} >
Reload
</Button>
<Table dataSource={dataSource} columns={columns} rowSelection={rowSelection} />;
</div>
);
}
export default App;
Maybe following example will make it clear for you:
import React, { useState } from "react";
import { Table, Button } from "antd";
import "antd/dist/antd.css";
import "./index.css";
export default function App() {
const columns = [
{
title: "Currency",
dataIndex: "сurrency",
key: "сurrency"
}
];
const data = [
{
key: "EUR",
сurrency: "€"
},
{
key: "USD",
сurrency: "$"
},
{
key: "RUB",
сurrency: "₽"
}
];
const [selectedRowsArray, setSelectedRowsArray] = useState([]);
const rowSelection = {
selectedRowKeys: selectedRowsArray,
onChange: (key) => {
setSelectedRowsArray(key);
exchangeMoney(key[0]);
}
};
function exchangeMoney(key) {
console.log(key);
}
return (
<>
<Table
columns={columns}
dataSource={data}
rowSelection={{ type: "radio", ...rowSelection }}
/>
<Button className="clear-btn" onClick={() => setSelectedRowsArray([])}>
CLEAR
</Button>
</>
);
}
see in codesandbox

Implementing a global search filter across react-table : React+ react-table

I am trying to implement a global search filter that searches for the key across the entire table. I am attaching a change handler and on every input I trigger a callback that searches that key across that data and the value is being set.It is getting filtered as I type-in the characters but I want the search to work when I enter multiple serach values like string1,string2 in the search input
Code Sandbox: https://codesandbox.io/s/jolly-bhabha-iqcx1
Code
import React from "react";
import ReactDOM from "react-dom";
import { Input } from "semantic-ui-react";
import ReactTable from "react-table";
import "react-table/react-table.css";
import "./styles.css";
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {
data: [
{ firstName: "aaaaa", status: "Pending", visits: 155 },
{ firstName: "aabFaa", status: "Pending", visits: 155 },
{ firstName: "adaAAaaa", status: "Approved", visits: 1785 },
{ firstName: "aAaaaa", status: "Approved", visits: 175 },
{ firstName: "adaSaaa", status: "Cancelled", visits: 165 },
{ firstName: "aasaaa", status: "Cancelled", visits: 157 },
{ firstName: "aweaaaaaewea", status: "Approved", visits: 153 },
{ firstName: "aaaaaa", status: "Submitted", visits: 155 }
],
columns: [],
searchInput: ""
};
}
componentDidMount() {
let columns = [
{
Header: "First Name",
accessor: "firstName",
sortable: false,
show: true,
displayValue: " First Name"
},
{
Header: "Status",
accessor: "status",
sortable: false,
show: true,
displayValue: "Status "
},
{
Header: "Visits",
accessor: "visits",
sortable: false,
show: true,
displayValue: " Visits "
}
];
this.setState({ columns });
}
handleChange = event => {
this.setState({ searchInput: event.target.value }, () => {
this.globalSearch();
});
};
globalSearch = () => {
let { data, searchInput } = this.state;
if (searchInput) {
let filteredData = data.filter(value => {
return (
value.firstName.toLowerCase().includes(searchInput.toLowerCase()) ||
value.status.toLowerCase().includes(searchInput.toLowerCase()) ||
value.visits
.toString()
.toLowerCase()
.includes(searchInput.toLowerCase())
);
});
this.setState({ data: filteredData });
}
};
render() {
let { data, columns, searchInput } = this.state;
return (
<div>
<br />
<Input
size="large"
name="searchInput"
value={searchInput || ""}
onChange={this.handleChange}
label="Search"
/>
<br />
<br />
<ReactTable
data={data}
columns={columns}
defaultPageSize={10}
className="-striped -highlight"
/>
</div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
This is not a problem with react-table. In the current implementation,
for the very first time, you're filtering from original data.
Second time when you try to filter, you're trying to filter results from previously filtered data(the current data in state object is filtered results of previous attempt).
I suggest to try(this is forked from yours): https://codesandbox.io/s/eloquent-clarke-w1ehv
Maintain your original data as immutable source, and filter from it every time your search input is changed rather than filtering from current data object in the state. Take a look at the fork I've attached.
If your data is coming from ajax call, you should probably maintain two state variables:
this.state = {
data: [],
filteredData: [],
columns: [],
searchInput: ""
};
componentDidMount() {
yourapicall.then(data => {
this.setState({
data // whatever data you get.
});
});
}
// And in your global search
globalSearch = () => {
let { searchInput, data } = this.state;
let filteredData = data.filter(value => {
return (
value.firstName.toLowerCase().includes(searchInput.toLowerCase()) ||
value.status.toLowerCase().includes(searchInput.toLowerCase()) ||
value.visits
.toString()
.toLowerCase()
.includes(searchInput.toLowerCase())
);
});
this.setState({ filteredData });
};
And conditionally render your react-table
<ReactTable
data={filteredData && filteredData.length ? filteredData : data}
columns={columns}
defaultPageSize={10}
className="-striped -highlight"
/>
Hope this is helpful!

return array of objects from props React JS

so I have the following component that is a dropdown list created using react-select.
import React from 'react'
import Select from 'react-select';
const options = [
{ value: 'chocolate', label: 'Chocolate' },
{ value: 'strawberry', label: 'Strawberry' },
{ value: 'vanilla', label: 'Vanilla' }
];
class MealsFilters extends React.Component {
constructor(props) {
super(props);
this.state = {
selectedOption: null,
};
}
handleChange = (selectedOption) => {
this.setState({ selectedOption });
console.log(`Option selected:`, selectedOption);
}
render() {
const { selectedOption } = this.state;
return (
<div className="container my-3">
<div className="row">
<div className="col-lg-4 col-md-6 col-sm-8">
<Select
isMulti
isSearchable
placeholder={"catégories"}
value={selectedOption}
onChange={this.handleChange}
options={options}
/>
</div>
</div>
</div>
)
}
}
export default MealsFilters;
the options variable is the default one from the docs. I actually need to replace its values by each meal category available.
To do so, as you can see, I need to create an array of objects with a value and a label.
this component accesses meal categories through props called meals that are like so:
console.log(this.props.meals);
=> [{
id: 0,
name: spaghettis,
category: italian,
price: 5.99},
{
id: 1,
name: hamburger,
category: american,
price: 7.99},
{
etc.
}, {}]
How can I take advantage of this.props.meals to get my options array of objects ?
EDIT: multiple meals can have the same category, and I need each category to only appear once in the options.
Map over your this.props.meals array, and create the needed options array,
<Select
isMulti
isSearchable
placeholder={"catégories"}
value={selectedOption}
onChange={this.handleChange}
options={this.props.meal.map(item=>({value: item.id, label: item.name}))}
/>
You could do something like this:
options={this.props.meals.map(
({id, name})=>({value:id,label:name})
)}
You could also use redux connect to create a container that will map the data to dropdown values for you
You can merge the data by category in the following way:
var items = [
{
id: 0,
name: 'spaghettis',
category: 'italian',
price: 5.99,
},
{
id: 1,
name: 'hamburger',
category: 'american',
price: 7.99,
},
{
id: 2,
name: 'other hamburger',
category: 'american',
price: 7.99,
},
];
console.log(
[
...items.reduce(
(result, item) => (
result.get(item.category)
? result.get(item.category).push(item.id)
: result.set(item.category, [item.id]),
result
),
new Map(),
),
].map(([label, value]) => ({ label, value })),
);
In the component it'll look like this:
options={[
...this.props.meals.reduce(
(result, item) => (
result.get(item.category)
? result.get(item.category).push(item.id)
: result.set(item.category, [item.id]),
result
),
new Map(),
),
].map(([label, value]) => ({ label, value }))}
You only need the "name" property so when you map through meals, simply retrieve it. Then upper case the first letter.
const meals = [{
id: 0,
name: "spaghettis",
category: "italian",
price: 5.99
},
{
id: 1,
name: "hamburger",
category: "american",
price: 7.99
}
]
const result = meals.map(({name}) => ({
label: `${name[0].toUpperCase()}${name.slice(1)}`,
value: name
}))
console.log(result);
You can use getOptionLabel and getOptionValue props.
<Select
options={this.props.meals},
getOptionLabel={m => m.name}
getOptionValue={m => m.id} />
https://react-select.com/props
getOptionLabel generic = (option) => string
Resolves option data to a string to be displayed as the label by components
getOptionValue generic = (option) => string
Resolves option data to a string to compare options and specify value attributes

React tables Calculating Footer sum on page change on Sort on search, how can we achieve that

React tables Calculating Footer sum on page change on Sort on search, how can we achieve that.
import React from "react";
import { render } from "react-dom";
import ReactTable from "react-table";
import "react-table/react-table.css";
const data = [
{
id: 1,
product: "apple",
stock: 1,
price: 123
},
{
id: 2,
product: "pie",
stock: 2,
price: 22
}
];
const App = () => (
<div>
<ReactTable
data={data}
columns={[
{
Header: "Id",
accessor: "id"
},
{
Header: "Product",
accessor: "product",
Footer: "Summary"
},
{
Header: "Stock",
accessor: "stock"
},
{
Header: "Price",
accessor: "price",
Footer: (
<span>{
data.reduce((total, { price }) => total += price, 0)
}</span>
)
}
]}
defaultPageSize={2}
/>
</div>
);
above code can be used to get the sum of a column data of all the rows, can anyone please guide me in a right way.
Import this first:
import _ from "lodash";
Then below code should resolve your issue:
{
Header: "Price",
accessor: "price",
id: "price"
Footer: <span>{_.sum(_.map(data, d => d.price))}</span>
)
}
Please note that there should be underscore symbol between { and .sum.
Similarly underscore symbol between ( and .map
Somehow it is removed when I posted my code here.

Categories

Resources