I already asked this question but got advice to ask again with more details.
I have project to load data from firebase in react-table, and that is done. Working perfectly. Problem is that from that database, there are pictures which need to be showed in table too. From first Picture you can see how data in firebase is organized.
firebase data
And here is code to load that data in react:
class App extends Component {
constructor(props) {
super(props);
this.state = {
vehicles: []
};
}
componentWillMount() {
this.getvehicles();
}
getvehicles() {
let vehicles = [];
firebase
.database()
.ref(`vehicles`)
.once('value', snapshot => {
snapshot.forEach(level1 => {
level1.forEach(level2 => {
const vehicle = level2.val();
vehicle.pictures && vehicles.push(vehicle);
});
});
this.setState({
vehicles
});
});
}
From second picture you can see that data is loaded from firebase
Data loaded from Firebase
And Render code is here:
render() {
const vehiclesColumns = [
{
columns: [
{
Header: 'Vehicle ID',
id: 'vehicleID',
accessor: d => d.vehicleID,
filterMethod: (filter, row) =>
row[filter.id].startsWith(filter.value)
},
{
Header: 'Terminal',
id: 'terminal',
accessor: d => d.terminal,
filterMethod: (filter, row) =>
row[filter.id].startsWith(filter.value)
},
{
Header: 'Time',
id: 'timestamp',
accessor: d => {
return Moment(d.timestamp)
.local()
.format('DD-MMMM-YYYY', 'at', true);
}
},
{
Header: 'User',
id: 'user',
accessor: d => d.user,
filterMethod: (filter, row) =>
row[filter.id].startsWith(filter.value)
}
]
}
];
return (
<div style={style}>
<div>
<ReactTable
style={{ marginLeft: '-80%', marginRight: '-80%' }}
data={this.state.vehicles}
filterable
defaultFilterMethod={(filter, row) =>
String(row[filter.id]) === filter.value
}
columns={vehiclesColumns}
SubComponent={row => {
return <div>PICTURES IN ROW</div>;
}}
/>
</div>
</div>
);
}
}
So my question is, anyone to help me, or rewrite the code, "pictures" array what you can see on second screenshot, render in "row" of "react-table" example:
SubComponent={row => {
return <div><img src={remoteUri} key={vehicle.picture} /></div>;
}}
As you can see on the last screenshot, how sould be and where to show "pictures" from Firebase.
REACT-TABLE DATA WITH PICTURES IN ROW
Already found solution:
Before "render" there is "chain" method to connect all pictures from one vehicle
getvehicles() {
firebase
.database()
.ref(`pictures`)
.once('value', snapshot => {
const data = snapshot.val();
const vehicles = _.chain(data)
.values()
.groupBy('vehicleId')
.map((rows, vehicleId) => ({
vehicleId,
pictures: _.map(rows, 'remoteUri')
}))
.value();
console.log(vehicles);
this.setState({ vehicles });
});
}
At "render"
const storage = firebase.storage();
const storageRef = storage.ref();
<div>
{row.original.pictures.map(ref => (
<Async
promiseFn={() => storageRef.child(ref).getDownloadURL()}
>
{({ isLoading, error, data }) => {
if (error) {
return 'FATALL ERROR';
}
if (isLoading) {
return 'Loading...';
}
if (data) {
return <img src={data} alt={data} key={data} />;
}
}}
</Async>
))}
</div>
With this code Im getting pictures in row of "Subcomponent" in React-table
Related
I am using reacttable-6 to render the data in table,but the is not showing up in table.It is giving me "No data found".Data is coming from api,even i console logged the response from api,the what data i am getting from is fine.I aslo hard coded the data,then the data is showing up in the table
I am not able to figure out what the issue is.Thanks inadvance.
import React,{useState} from 'react'
import ReactTable from "react-table-6";
import 'react-table-6/react-table.css';
import axios from "axios";
export default function Inventory(){
var compdata = [
{
FirstName: "Chandu",
LastName: "Reddy",
_id: "63c5766f9d9de1b624481574",
Discription: {
_id: "63c5766f9d9de1b624481574",
DOB: "Havells",
Age: "HiBreak",
},
Address: "Something",
}
];
const handleDelete=(data)=>{
console.log(data)
}
const handleEdit=()=>{
console.log("dcdc")
}
const column = [
{
Header: "FirstName",
accessor: "FirstName",
sortable: false
},
{
Header: "LastName",
accessor: "LastName",
sortable: false
},
{
Header: "Address",
accessor: "Address",
sortable: false
},
{
Header: "Actions",
Cell: (row) => (
<div>
<a onClick={() => handleEdit(row.original)}>
Edit
</a>
<a onClick={() => handleDelete(row.original)}>
Delete
</a>
</div>
)
}
];
const [data1, setData1] = useState([]);
const [columns, setColumns] = useState(column);
const { toggle } = useContext(ThemeContext);
useEffect(()=>{
const fetch = async () => {
await axios
.get(`http://localhost:4001/api/uploadCsv/getData`)
.then((res) => {
setData1(res.data);
console.log(res.data)
});
};
fetch();
},[setData1]);
const [expanded, setExpanded] = useState({});
const onExpandedChange = (newExpanded) => {
setExpanded(newExpanded);
};
return(
<div className="container">
<div className='Table-container'>
<ReactTable
data={data1}
columns={columns}
defaultPageSize={data1.length}
showPagination={false}
resizable={false}
expanded={expanded}
// className="-striped -highlight"
getTrProps={(state, rowInfo, column, instance, expanded) => {
return rowInfo
? {
onClick: (expanded) => {
const newExpanded = { ...expanded };
newExpanded[rowInfo.viewIndex] = expanded[rowInfo.viewIndex]
? false
: true;
setExpanded(newExpanded);
}
}
: {};
}}
SubComponent={(row) => {
return (
<div style={{ padding: "20px" }}>
<em>{(row.original.Discription.Make)}</em>K <br />
</div>
);
}}
/>
<br />
</div>
</div>
)
}
Screen shot for reference
Change your useEffect like this and add another to check did data1 updated yet. Depend on data1 have value or not we will have different way to solve this
useEffect(() => {
axios.get(`http://localhost:4001/api/uploadCsv/getData`).then((res) => {
setData1(res.data);
});
}, []);
useEffect(()=>{
console.log(data1)
},[data1])
I am getting data from my database to display it on the graph. Currently, I will have to refresh the page for the graph to update. I would like to refresh the graph in x interval as my data will be inserted at x interval. Am using ant design for the graph plotting. I am using a 'home' to display my graph and another class for my data fetching.
Home.js
export class Home extends Component {
static displayName = Home.name;
render () {
return (
<div>
<h1>Dashboard</h1>
<h2>
<div className="site-card-wrapper">
Graph1
<Graph />}
</div>
</h2>
</div>
);
}
}
Temp.js
const TempGraph = () => {
const [data, setData] = useState([]);
useEffect(() => {
asyncFetch();
}, []);
const asyncFetch = () => {
fetch('link')
.then((response) => response.json())
.then((json) => setDatajson))
.catch((error) => {
console.log('fetch data failed', error);
});
};
const config = {
data,
xField: 'time',
yField: 'value',
seriesField:'location',
xAxis: {
title: {
text: 'Hours',
}
},
yAxis:{
title:{
text: 'Temperature in °',
}
},
meta: {
time: {
alias: 'hours',
},
value: {
alias: 'temperature',
max: 50,
},
},
};
return <Line {...config} />;
}
export default TempGraph;
You could just add a setInterval in your useEffect to grab the data and update them again. Don't forgot to clear the interval on return:
useEffect(() => {
const interval = setInterval(() => asyncFetch(), 5000)
return () => clearInterval(interval)
}, []}
This example triggers every 5000ms, change the value according to your needs.
I would like to style my cell's rating into star by using Material-Table,
like the original Material-UI provided:
https://material-ui.com/components/rating/
Is it possible to use in Material-Table? I cannot find document related to this...just for the style for background, color, etc., not for writing functions in cell style.
https://material-table.com/#/docs/features/styling
thanks a lot!
You can use material-table's custom edit component to render the mui Rating component.
Full Working demo
Sample code snippet of columns array
const columns = propValue => [
{ title: "Id", field: "id" },
{ title: "First Name", field: "first_name" },
{
title: "Rating",
field: "rating",
render: rowData => {
return <Rating name="hover-feedback" value={rowData.rating} readOnly />;
},
editComponent: props => (
<Rating
name="hover-feedback"
value={props.value}
onChange={(event, newValue) => {
props.onChange(newValue);
}}
/>
),
cellStyle: {
backgroundColor: "#039be5",
color: "#FFF"
},
width: "30%"
}
];
Component
class App extends Component {
tableRef = React.createRef();
propValue = true;
state = { data: [] };
componentDidMount() {
const query = 0;
let url = "https://reqres.in/api/users?";
url += "per_page=" + query.pageSize;
url += "&page=" + (query.page + 1);
fetch(url)
.then(response => response.json())
.then(result => {
console.log("result", result);
this.setState({
data: result.data.map(d => ({ ...d }))
});
});
}
render() {
return (
<div style={{ maxWidth: "100%" }}>
<MaterialTable
icons={tableIcons}
tableRef={this.tableRef}
columns={columns(this.propValue)}
editable={{
onRowUpdate: (newData, oldData) =>
new Promise((resolve, reject) => {
console.log("newData", newData);
console.log("oldData", oldData);
const dataUpdate = [...this.state.data];
const index = oldData.tableData.id;
dataUpdate[index] = newData;
this.setState({ data: dataUpdate }, () => {
console.log("xx", this.state.data);
resolve(this.state);
});
})
}}
data={this.state.data}
title="Remote Data Example"
options={{ tableLayout: "fixed" }}
/>
<button
onClick={() => {
this.tableRef.current.onQueryChange();
}}
>
ok
</button>
</div>
);
}
}
I use react-table npm package and i store all the data required by the table in the state
componentDidMount() {
this.props.client
.query({
query: ALL_SKUS
})
.then(({ data }) => {
const skus = removeTypename(data.allSkuTypes);
const newData = skus.map((sku, index) => ({
serial: index + 1,
...sku
}));
this.setState({ data: newData });
})
.catch(err => {
console.log(err);
});
}
this is how the 'name' field of my column looks like
{
Header: 'SKU Name',
headerClassName: 'vt-table-header',
accessor: 'name',
maxWidth: 350,
Cell: this.renderEditable
},
where this is the event handler
renderEditable = ({ index, column }) => {
const { data } = this.state;
return (
<InputGroup
onChange={e => {
const newData = [...data];
newData[index][column.id] = e.target.value;
this.setState({ data: newData });
}}
value={data[index][column.id]}
/>
);
};
finally this is how all that data goes in the react table
<ReactTable
loading={data.length === 0 ? true : false}
showPagination={false}
className="mt-3 text-center"
data={data}
columns={columns}
/>
I have tried removing the value attribute from the Input and then added an onBlur to it while that solved the performance issue it was enable to fetch the data from the query initially.
I am also facing this issue in many complex forms in my application any help will be highly appreciated
Here is an idea.
instead of doing this, which provides a component InputGroup for your Cells in the table as I suppose:
renderEditable = ({ index, column }) => {
const { data } = this.state;
return (
<InputGroup
onChange={e => {
const newData = [...data];
newData[index][column.id] = e.target.value;
this.setState({ data: newData });
}}
value={data[index][column.id]}
/>
);
};
What about creating a separate component that controlls it's own state, instead of changing the whole table state for each cell change, why not have a component CELL which changes it's own state with any other possible POST requests ...etc.
This will narrow-down the rendering to Cell based instead of the whole Table gets rendered.
It will almost be the same:
class Cell extends React.Component {
state = { ...yourCellData }
componentDidMount() {
this.setState({ ...this.props.youCellData }); //any properties passed from the main component.
}
render(){
const { index, column } = this.props;
return (
<InputGroup
onChange={e => {
const newData = [...this.state.data];
newData[index][column.id] = e.target.value;
this.setState({ data: newData }); //this now modifies the Cell data instead of the whole table
}}
value={data[index][column.id]}
/>
);
}
}
Applicable possible as:
{
Header: 'SKU Name',
headerClassName: 'vt-table-header',
accessor: 'name',
maxWidth: 350,
Cell: (index, column) => <YourNewCellComponent index={index} column={column} />
},
I hope this somehow provides you of an overall of an approach that might solve the problem
I'm new in React. Using react-table component to render data from firebase and that is working well.
constructor(props) {
super(props);
this.state = {
vehicles: []
};
}
getvehicles() {
let vehicles = [];
firebase
.database()
.ref(`vehicles`)
.once('value', snapshot => {
snapshot.forEach(level1 => {
level1.forEach(level2 => {
const vehicle = level2.val();
vehicle.pictures && vehicles.push(vehicle);
});
});
this.setState({
vehicles
});
});
}
From here Data comming in react-table
return (
<div style={style}>
<div>
<ReactTable
style={{ marginLeft: '-80%', marginRight: '-80%' }}
data={this.state.vehicles}
filterable
defaultFilterMethod={(filter, row) =>
String(row[filter.id]) === filter.value
}
columns={vehiclesColumns}
SubComponent={row => {
return ;
}}
/>
</div>
</div>
);
Problem is, that I'm getting "pictures" from database, and want to put them in "subcomponent" and I do not know how? Anyone to help?
SubComponent={row => {
return (
<div>
some code here
</div>
);
Image 1 Example of data loaded from firebase
Image 2 Example of table "click on arrow and show pics from database"
=====================
New question
Ok on the end I manage to make all together but still getting error 'imageUrls' is not defined.
For me this is nightmare to find where is problem, so is there anyone who can re-check this code totally and just make comment how to fix and where is problem?!
import React, { Component } from 'react';
import ReactTable from 'react-table';
import 'react-table/react-table.css';
import firebase from 'firebase';
import Moment from 'moment';
import { storage } from 'firebase';
import _ from 'underscore';
export const getFileByPath = async query =>
await storage
.ref()
.child(query)
.getDownloadURL();
class App extends Component {
constructor(props) {
super(props);
this.state = {
vehicles: []
};
this.state = {
imageUrls: []
};
}
prepareImages = () => {
Promise.all(
_.map(this.props.images, image => {
return storage.getFileByPath(image.remoteUri);
})
).then(results =>
_.each(results, result => {
const imageUrls = this.state.imageUrls;
imageUrls.push(result);
this.setState({ imageUrls: imageUrls, loading: false });
})
);
};
componentWillMount() {
this.getvehicles();
}
getvehicles() {
let vehicles = [];
firebase
.database()
.ref(`vehicles`)
.once('value', snapshot => {
snapshot.forEach(level1 => {
level1.forEach(level2 => {
const vehicle = level2.val();
vehicle.pictures && vehicles.push(vehicle);
});
});
this.setState({
vehicles
});
});
}
render() {
const vehiclesColumns = [
{
columns: [
{
Header: 'Vehicle ID',
id: 'vehicleID',
accessor: d => d.vehicleID,
filterMethod: (filter, row) =>
row[filter.id].startsWith(filter.value)
},
{
Header: 'Terminal',
id: 'terminal',
accessor: d => d.terminal,
filterMethod: (filter, row) =>
row[filter.id].startsWith(filter.value)
},
{
Header: 'Time',
id: 'timestamp',
accessor: d => {
return Moment(d.timestamp)
.local()
.format('DD-MMMM-YYYY', 'at', true);
},
filterMethod: (filter, row) =>
row[filter.id].startsWith(filter.value)
},
{
Header: 'User',
id: 'user',
accessor: d => d.user,
filterMethod: (filter, row) =>
row[filter.id].startsWith(filter.value)
}
]
}
];
return (
<div style={style}>
<div>
<ReactTable
style={{ marginLeft: '-80%', marginRight: '-80%' }}
data={this.state.vehicles}
filterable
defaultFilterMethod={(filter, row) =>
String(row[filter.id]) === filter.value
}
columns={vehiclesColumns}
SubComponent={row => {
return (
<div>
{_.map(imageUrls, image => (
<img src={image} key={image} />
))}
</div>
);
}}
/>
</div>
</div>
);
}
}
const style = {
display: 'flex',
justifyContent: 'center'
};
export default App;
I think what you are trying to do is something like:
// Somewhere else, maybe a different doc
const SubComponent = () => {
<div>Content here</div>
}
// [...previous Code]
return (
<ReactTable
style={{ marginLeft: "-80%", marginRight: "-80%" }}
data={this.state.vehicles}
filterable
defaultFilterMethod={(filter, row) =>
String(row[filter.id]) === filter.value
}
columns={vehiclesColumns}
>
<SubComponent props={somePropsHere} />
</ReactTable>
)
Am I right? The children of a Component should not be given as a property.
Regards