I am using Axios to fetch data from an API in React. I have a search component that runs the request on input change. I am then making a table with the rows
data using MDB Datatables
The first time the table is rendered, it works great. However, it doesn't render with fresh data despite Axios retrieving it when the search box changes. I discovered that I could manually trigger a table refresh by making any edit to datatable.columns
(eg. changing a width
property from 50
to 55
)
I am using App.js
and two components: Search.js
and DataTable.js
I believe I need to update the state of the rows
property of datatable. The columns
section are the hardcoded table headers which don't change.
How can I accomplish this?
App.js
import './App.css';
import {useState, useEffect} from "react"
import axios from 'axios'
import Search from './components/UI/Search'
import DataTable from "./components/UI/DataTable";
function App() {
const [items, setItems] = useState([])
const [query, setQuery] = useState(true)
useEffect(() => {
const fetchItems = async () => {
const result = await axios(`https://services1.arcgis.com/0MSEUqKaxRlEPj5g/arcgis/rest/services/ncov_cases_US/FeatureServer/0/query?where=Province_State%20%3D%20'${query}'&outFields=*&returnGeometry=false&&outSR=4326&f=json`)
const cleanResult = result.data.features
setItems(cleanResult)
}
fetchItems()
// fires off every time ~query~ changes because dependency
}, [query])
return (
<div className="container">
<div className='text-4xl px-10 py-4'>Covid data</div>
<Search getQuery={(q) => setQuery(q)}/>
<DataTable items={items}/>
</div>
);
}
export default App;
DataTable.js
import React from 'react';
import {useState} from "react";
import {MDBDataTableV5} from 'mdbreact';
export default function Basic({items}) {
let newItems = items.map(function (item, index) {
return {
id: (index + 1),
Admin2: item.attributes.Admin2,
State: item.attributes.Province_State,
Incident_Rate: Math.round(item.attributes.Incident_Rate),
Confirmed: item.attributes.Confirmed,
Deaths: item.attributes.Deaths,
Last_Update: new Date(item.attributes.Last_Update).toLocaleDateString(),
}
});
let [datatable, setDatatable] = React.useState({
columns: [
{
label: 'Region',
field: 'Admin2',
width: 140,
attributes: {
'aria-controls': 'DataTable',
'aria-label': 'Name',
},
},
{
label: 'State',
field: 'State',
width: 120,
},
{
label: 'Incident Rate',
field: 'Incident_Rate',
width: 100,
},
{
label: 'Confirmed',
field: 'Confirmed',
width: 120,
},
{
label: 'Deaths',
field: 'Deaths',
width: 55,
},
{
label: 'Last Update',
field: 'Last_Update',
width: 55,
},
],
// use fetched content for table rows
rows: newItems
}
);
// return MDB DataTable
return <MDBDataTableV5 hover entriesOptions={[5, 20, 25, 100]} entries={25} pagesAmount={4} data={datatable}
fullPagination/>;
}
Search.js
(I don't think this needs to change)
import React, {useState} from 'react';
const Search = ({getQuery}) => {
const [text, setText] = useState('')
const onChange = (q) => {
setText(q)
getQuery(q)
}
return (
<section className='search px-10 py-4'>
<form>
<label className="block">
<span className="block text-xl font-medium text-slate-700">Search</span>
<input
type='text'
className='form-control mt-1 block w-full px-3 py-2 bg-white border border-slate-300 rounded-md text-sm shadow-sm placeholder-slate-400
focus:outline-none focus:border-sky-500 focus:ring-1 focus:ring-sky-500'
placeholder='Georgia'
value={text}
onChange={(e) => onChange(e.target.value)}
autoFocus/>
</label>
</form>
</section>
);
};
export default Search;