React-Admin - How to create a Datagrid without a List in React-Admin - datagrid

How to create a Datagrid without a List in React-Admin?
In React-admin to be able to use Datagrid to show the values you need to nest it inside a List like that:
<List {...props}>
<Datagrid>
<Textfield source"name" />
<Datagrid />
<List/>
But I need to use the dDatagrid outside of the List. The values of the Datagrid must to be shown in a screen of the type inside a Tab.

Here how I solved that problem using React-Admin 2.9
First I used The import { Query } from 'react-admin'; to fetch the data from the endpoint data/product and after that It converted the IDs to the key of it's own data.
To the commponent CustomDatagrid was passed two arrays the will be used to show the values. The first is a array of IDs and the second array is the array that contains the data and uses IDs as its key to be able to access the values.
ProductShow.js
import React, { useState } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import {
TextField,
Query,
showNotification,
// ReferenceField,
DateField,
} from 'react-admin';
import CustomDatagrid from './CustomDatagrid';
const convertKeyToIndice = (datas) => {
const { data } = datas;
let ids = [];
const dataKey = [];
if (data) {
ids = data.map((elemento) => {
dataKey[elemento.id] = elemento;
return elemento.id;
});
return ({ ids, dataKey });
}
return ({});
};
const ProductShow = (props) => {
const { record } = props;
const { productId, dateValue } = record;
const [newPage, setNewPage] = useState(0);
const [rowsPerPage, setRowsPerPage] = useState(50);
const filter = {
pagination: { page: newPage + 1, perPage: rowsPerPage },
sort: { field: 'id', order: 'ASC' },
filter: { productId, dateValue: dateValue },
};
return (
<Query type="GET_LIST" resource="data/product" payload={filter}>
{(datas) => {
if (datas.loading && !datas.error) { return <div>Wait...</div>; }
if (datas.error) {
props.showNotification('Not Found');
return <div />;
}
const dataGridValues = {
...convertKeyToIndice(datas),
total: datas.total,
rowsPerPage,
setRowsPerPage,
newPage,
setNewPage,
};
return (
<>
<CustomDatagrid dataGridValues={dataGridValues}>
{/* <ReferenceField
sortBy="product.id"
source="productId"
reference="product"
linkType={false}
allowEmpty
{...props}
label="product"
>
<TextField source="name" />
</ReferenceField> */}
<DateField label="Date" source="valueDate" showTime />
<TextField label="Value1" source="value1" />
<TextField label="Value2" source="value2" />
<TextField label="Value3" source="value3" />
<TextField label="Value4" source="value4" />
<TextField label="Value5" source="value5" />
</CustomDatagrid>
</>
);
}}
</Query>
);
};
ProductShow.propTypes = {
productId: PropTypes.string.isRequired,
dateValue: PropTypes.string.isRequired,
showNotification: PropTypes.func.isRequired,
record: PropTypes.oneOfType([PropTypes.object]).isRequired,
};
export default connect(null, { showNotification })(ProductShow);
In the TableHead it shows the label of each column following the order that you wrap the Components in the CustomDatagrid inside the parent ProductShow component.
To Show The Components Like the List of React-Admin would show, is used the
{React.cloneElement(child,
{ record: dataKey[id] },
(child.props.children ? child.props.children : null))}
CustomDatagrid.js
import React from 'react';
import {
Table,
TableRow,
TableHead,
TableCell,
TableBody,
TablePagination,
} from '#material-ui/core';
import PropTypes from 'prop-types';
const CustomDatagrid = (propsDataGrid) => {
const { children, dataGridValues } = propsDataGrid;
const {
dataKey,
ids,
total,
rowsPerPage,
setRowsPerPage,
setNewPage,
newPage,
} = dataGridValues;
const handleChangePage = (event, page) => {
setNewPage(page);
};
const handleChangeRowsPerPage = (event) => {
const vlrDecimal = parseInt(event.target.value, 10);
setRowsPerPage(vlrDecimal);
setNewPage(0);
};
return (
<>
<Table style={{ width: '100%' }}>
<TableHead>
<TableRow>
{children && children.map(({ props }) => (
<TableCell>
{props && props.label ? props.label : props.source}
</TableCell>
))
}
</TableRow>
</TableHead>
<TableBody>
{ids && ids.map(id => (
<TableRow>
{React.Children.map(children,
child => (
<TableCell>
{React.cloneElement(child,
{ record: dataKey[id] },
(child.props.children ? child.props.children : null))}
</TableCell>
))}
</TableRow>
))
}
</TableBody>
</Table>
<TablePagination
rowsPerPageOptions={[50, 100, 250]}
component="div"
count={total}
rowsPerPage={rowsPerPage}
page={newPage}
onChangePage={handleChangePage}
onChangeRowsPerPage={handleChangeRowsPerPage}
labelRowsPerPage="Results per Page:"
/>
</>
);
};
CustomDatagrid.propTypes = {
source: PropTypes.string.isRequired,
label: PropTypes.string.isRequired,
};
export default CustomDatagrid;

Related

react table add class cell with editTable

I use react table v7 with editable as defaultColumn, I have a log that returns the index row and the column index.
Is it possible to add a class to the cell if the index row and index column crosses.
my log that returns the row and column index :
const log = {rowIndex:1, columnIndex:10}
The expected result :
editable component :
import React, { useEffect, useState } from 'react';
import { OverlayTrigger, Tooltip } from 'react-bootstrap';
const EditableCell = ({
value: initialValue,
row: { index },
column: { id },
updateMyData,
}: {
value: any;
row: any;
column: any;
updateMyData: any;
}) => {
const [value, setValue] = useState(initialValue);
const [textCount, setTextCount] = useState<number>(0);
const tooltipName = <Tooltip id="tooltipName">{value}</Tooltip>;
const onChange = (e: any) => {
setValue(e.target.value);
};
const onBlur = () => {
updateMyData(index, id, value);
};
useEffect(() => {
setValue(initialValue);
}, [initialValue]);
useEffect(() => {
if (value) {
setTextCount(value.length);
}
}, [value]);
return (
<>
{textCount > 15 ? (
<OverlayTrigger placement="top" overlay={tooltipName}>
<input value={value} onChange={onChange} onBlur={onBlur} />
</OverlayTrigger>
) : (
<>
<input value={value} onChange={onChange} onBlur={onBlur} />
</>
)}
</>
);
};
export default EditableCell;
grid :
import React from 'react';
import { Table } from 'react-bootstrap';
import { useSortBy, useTable } from 'react-table';
import GridRow from './grid-row';
import GridTfoot from './grid-tfoot';
import GridThead from './grid-thead';
import EditableCell from './grid-editable';
const SimpleGrid = (props: {
rows: any[];
columns: any;
extraCssClassName: string;
updateMyData?: any;
defaultSort?: any[];
editable?: boolean;
}) => {
const defaultColumn = {
Cell: EditableCell,
};
const {
getTableProps,
getTableBodyProps,
headerGroups,
footerGroups,
rows,
prepareRow,
} = useTable(
{
columns: props.columns,
data: props.rows,
initialState: {
sortBy: props.defaultSort,
},
defaultColumn: props.editable ? defaultColumn : undefined,
updateMyData: props.updateMyData,
},
useSortBy
);
return (
<Table
className={`table-nostriped grid-simple mb-0 ${props.extraCssClassName}`}
responsive
size="sm"
{...getTableProps()}
>
<GridThead headers={headerGroups} />
<tbody {...getTableBodyProps()}>
{rows.map((row, i) => {
prepareRow(row);
return <GridRow row={row} key={i} />;
})}
</tbody>
<GridTfoot footerGroups={footerGroups} />
</Table>
);
};
SimpleGrid.defaultProps = { extraCssClassName: '', defaultSort: [] };
export default SimpleGrid;
updateMyData :
const updateMyData = (rowIndex: any, columnId: any, value: any) => {
setData((old: any) =>
old.map((row: any, index: any) => {
if (index === rowIndex) {
return {
...old[rowIndex],
[columnId]: value,
};
}
return row;
})
);
};

Show only current tooltip in a Tree

I have created a custom component in order to add tooltip to each one of the nodes in a Tree.
function StyledTreeItem(props) {
const { nodeId, labelText, tooltipTitle, ...other } = props;
return (
<Tooltip title={tooltipTitle} placement="left">
<TreeItem nodeId={nodeId} label={labelText} {...other} />
</Tooltip>
)};
export default function HierarchyTree(props) {
const journeyFilterDataTest = [
{
account: ["1551", "4000"],
campaign: 'DEFECT',
name: 'XXXX'
}
]
return (
<TreeView
defaultCollapseIcon={<ExpandMoreIcon />}
defaultExpandIcon={<ChevronRightIcon />}>
<StyledTreeItem nodeId="1" labelText={journeyFilterDataTest[0].campaign} tooltipTitle="Category">
<StyledTreeItem nodeId="2" labelText={journeyFilterDataTest[0].name} tooltipTitle="Name" >
{journeyFilterDataTest[0].account.map(item => {
return <StyledTreeItem key={item} nodeId={item} labelText={item} tooltipTitle="Account" />
})}
</StyledTreeItem>
</StyledTreeItem>
</TreeView>
The problem is that when I hover over one of the child nodes, then all the tooltips will be active (show on the UI).
How can I make sure that only the current node that the user is hovering will show the tooltip?
Thank you
that's because your nodeId is not unique. Make it unique, then it will show only the tooltip of hovered item . Refer to this sandbox here.
App.js (exanple of Tree - looping through list of items)
passing item id as unique id for TreeItem nodeId
use a state of parentsClick to keep track of parent tree clicked. If a parent was clicked, then only return TreeItem without Tooltip. Otherwise return all.
import React, { useState } from "react";
import "./styles.css";
import { makeStyles } from "#material-ui/core/styles";
import { TreeItem, TreeView } from "#material-ui/lab";
import { Tooltip } from "#material-ui/core";
import ExpandMoreIcon from "#material-ui/icons/ExpandMore";
import ChevronRightIcon from "#material-ui/icons/ChevronRight";
export default function App() {
const classes = useStyles();
const [parentsClick, setParentsClick] = useState([]);
const firstLevel = [
{
id: "1",
label: "Applications",
secondLevel: [
{ id: "1a", label: "Calendar", thirdLevel: [] },
{ id: "1b", label: "Chrome", thirdLevel: [] },
{ id: "1c", label: "Webstorm", thirdLevel: [] }
]
},
{
id: "2",
label: "Documents",
secondLevel: [
{ id: "2a", label: "Oss", thirdLevel: [] },
{ id: "2b", label: "Material-UI", thirdLevel: [] }
]
}
];
const StyledTreeItem = (props) => {
if (parentsClick.includes(props.id))
return <TreeItem nodeId={props.id} label={props.label} {...props} />;
else
return (
<Tooltip title={props.label} placement="left">
<TreeItem nodeId={props.id} label={props.label} {...props} />
</Tooltip>
);
};
return (
<TreeView
className={classes.root}
defaultCollapseIcon={<ExpandMoreIcon />}
defaultExpandIcon={<ChevronRightIcon />}
>
{firstLevel.length > 0 &&
firstLevel.map((item1stLvl) => (
<StyledTreeItem
key={item1stLvl.id}
id={item1stLvl.id}
label={item1stLvl.label}
onClick={() => {
if (parentsClick.includes(item1stLvl.id))
setParentsClick(() =>
parentsClick.filter((item) => item !== item1stLvl.id)
);
else setParentsClick([item1stLvl.id, ...parentsClick]);
}}
>
{item1stLvl.secondLevel.length > 0 &&
item1stLvl.secondLevel.map((item2ndLvl) => (
<StyledTreeItem
key={item2ndLvl.id}
id={item2ndLvl.id}
label={item2ndLvl.label}
/>
))}
</StyledTreeItem>
))}
</TreeView>
);
}
const useStyles = makeStyles({
root: {
height: 240,
flexGrow: 1,
maxWidth: 400
}
});

changing Material-ui table style in row.getRowProps()

In my react application I'm using Material-UI enhanced table which is based on react-table and I would like to change the style of their rows.
Reading from documentation (https://material-ui.com/api/table-row/) in the component TableRow should be used the prop "classes" to change the style, but in the MaterialUi code props are read this way:
<TableRow {...row.getRowProps()}>
My question is how can I use the prop classes if the TableRow props are added automatically? I thought I needed to have this:
<TableRow classes="rowStyle ">
where rowStyle is:
const styles = {
rowStyle : {
padding: 10,
border: "1px solid red"
}
};
But obviously I can't this way, how can I add "classes" to the getRowProps() and the new style in it?
I couldn't find an explanation or a good example in official documentation or stackOverflow
Many thanks for the help
EnhancedTable.js:
import React from "react";
import Checkbox from "#material-ui/core/Checkbox";
import MaUTable from "#material-ui/core/Table";
import PropTypes from "prop-types";
import TableBody from "#material-ui/core/TableBody";
import TableCell from "#material-ui/core/TableCell";
import TableContainer from "#material-ui/core/TableContainer";
import TableFooter from "#material-ui/core/TableFooter";
import TableHead from "#material-ui/core/TableHead";
import TablePagination from "#material-ui/core/TablePagination";
import TablePaginationActions from "./TablePaginationActions";
import TableRow from "#material-ui/core/TableRow";
import TableSortLabel from "#material-ui/core/TableSortLabel";
import TableToolbar from "./TableToolbar";
import {
useGlobalFilter,
usePagination,
useRowSelect,
useSortBy,
useTable,
} from "react-table";
const IndeterminateCheckbox = React.forwardRef(
({ indeterminate, ...rest }, ref) => {
const defaultRef = React.useRef();
const resolvedRef = ref || defaultRef;
React.useEffect(() => {
resolvedRef.current.indeterminate = indeterminate;
}, [resolvedRef, indeterminate]);
return (
<div>
<Checkbox ref={resolvedRef} {...rest} />
</div>
);
}
);
const inputStyle = {
padding: 0,
margin: 0,
border: 0,
background: "transparent",
};
// Create an editable cell renderer
const EditableCell = ({
value: initialValue,
row: { index },
column: { id },
updateMyData, // This is a custom function that we supplied to our table instance
}) => {
// We need to keep and update the state of the cell normally
const [value, setValue] = React.useState(initialValue);
const onChange = (e) => {
setValue(e.target.value);
};
// We'll only update the external data when the input is blurred
const onBlur = () => {
updateMyData(index, id, value);
};
// If the initialValue is changed externall, sync it up with our state
React.useEffect(() => {
setValue(initialValue);
}, [initialValue]);
return (
<input
style={inputStyle}
value={value}
onChange={onChange}
onBlur={onBlur}
/>
);
};
EditableCell.propTypes = {
cell: PropTypes.shape({
value: PropTypes.any.isRequired,
}),
row: PropTypes.shape({
index: PropTypes.number.isRequired,
}),
column: PropTypes.shape({
id: PropTypes.number.isRequired,
}),
updateMyData: PropTypes.func.isRequired,
};
// Set our editable cell renderer as the default Cell renderer
const defaultColumn = {
Cell: EditableCell,
};
const EnhancedTable = ({
columns,
data,
setData,
updateMyData,
skipPageReset,
}) => {
const {
getTableProps,
headerGroups,
prepareRow,
page,
gotoPage,
setPageSize,
preGlobalFilteredRows,
setGlobalFilter,
state: { pageIndex, pageSize, selectedRowIds, globalFilter },
} = useTable(
{
columns,
data,
defaultColumn,
autoResetPage: !skipPageReset,
// updateMyData isn't part of the API, but
// anything we put into these options will
// automatically be available on the instance.
// That way we can call this function from our
// cell renderer!
updateMyData,
},
useGlobalFilter,
useSortBy,
usePagination,
useRowSelect,
(hooks) => {
hooks.allColumns.push((columns) => [
// Let's make a column for selection
{
id: "selection",
// The header can use the table's getToggleAllRowsSelectedProps method
// to render a checkbox. Pagination is a problem since this will select all
// rows even though not all rows are on the current page. The solution should
// be server side pagination. For one, the clients should not download all
// rows in most cases. The client should only download data for the current page.
// In that case, getToggleAllRowsSelectedProps works fine.
Header: ({ getToggleAllRowsSelectedProps }) => (
<div>
<IndeterminateCheckbox {...getToggleAllRowsSelectedProps()} />
</div>
),
// The cell can use the individual row's getToggleRowSelectedProps method
// to the render a checkbox
Cell: ({ row }) => (
<div>
<IndeterminateCheckbox {...row.getToggleRowSelectedProps()} />
</div>
),
},
...columns,
]);
}
);
const handleChangePage = (event, newPage) => {
gotoPage(newPage);
};
const handleChangeRowsPerPage = (event) => {
setPageSize(Number(event.target.value));
};
const removeByIndexs = (array, indexs) =>
array.filter((_, i) => !indexs.includes(i));
const deleteUserHandler = (event) => {
const newData = removeByIndexs(
data,
Object.keys(selectedRowIds).map((x) => parseInt(x, 10))
);
setData(newData);
};
const addUserHandler = (user) => {
const newData = data.concat([user]);
setData(newData);
};
// Render the UI for your table
return (
<TableContainer>
<TableToolbar
numSelected={Object.keys(selectedRowIds).length}
deleteUserHandler={deleteUserHandler}
addUserHandler={addUserHandler}
preGlobalFilteredRows={preGlobalFilteredRows}
setGlobalFilter={setGlobalFilter}
globalFilter={globalFilter}
/>
<MaUTable {...getTableProps()}>
<TableHead>
{headerGroups.map((headerGroup) => (
<TableRow {...headerGroup.getHeaderGroupProps()}>
{headerGroup.headers.map((column) => (
<TableCell
{...(column.id === "selection"
? column.getHeaderProps()
: column.getHeaderProps(column.getSortByToggleProps()))}
>
{column.render("Header")}
{column.id !== "selection" ? (
<TableSortLabel
active={column.isSorted}
// react-table has a unsorted state which is not treated here
direction={column.isSortedDesc ? "desc" : "asc"}
/>
) : null}
</TableCell>
))}
</TableRow>
))}
</TableHead>
<TableBody>
{page.map((row, i) => {
prepareRow(row);
return (
<TableRow {...row.getRowProps()}>
{row.cells.map((cell) => {
return (
<TableCell {...cell.getCellProps()}>
{cell.render("Cell")}
</TableCell>
);
})}
</TableRow>
);
})}
</TableBody>
<TableFooter>
<TableRow>
<TablePagination
rowsPerPageOptions={[
5,
10,
25,
{ label: "All", value: data.length },
]}
colSpan={3}
count={data.length}
rowsPerPage={pageSize}
page={pageIndex}
SelectProps={{
inputProps: { "aria-label": "rows per page" },
native: true,
}}
onChangePage={handleChangePage}
onChangeRowsPerPage={handleChangeRowsPerPage}
ActionsComponent={TablePaginationActions}
/>
</TableRow>
</TableFooter>
</MaUTable>
</TableContainer>
);
};
EnhancedTable.propTypes = {
columns: PropTypes.array.isRequired,
data: PropTypes.array.isRequired,
updateMyData: PropTypes.func.isRequired,
setData: PropTypes.func.isRequired,
skipPageReset: PropTypes.bool.isRequired,
};
export default EnhancedTable;
Correct me if i'm wrong, but i think the first step to your solution is the correct definition of styles for the material-ui element. I can't say for certain if there is another way to generate these styles, but a simple object such as:
const inputStyle = { padding: 0, margin: 0, border: 0, background: "transparent", };
will probably not work. You probably have to use the material styles for that.
import { makeStyles } from "#material-ui/core/styles";
const useStyles = makeStyles({
root: {
border: "1px solid red",
padding: 10
},
});
and then you have to use the style hook in the component definition:
const classes = useStyles();
When overriding a material-ui definition this part is the important one to define which part is going to overriden (not allowed to include pictures yet, sorry):
Material-Ui CSS keys for Table Row
Then you can override the style <TableRow classes={{ root: classes.root }}> or in your case maybe more like <TableRow classes={{ root: classes.root }} {...row.getRowProps()}>
An additional problem you might face is that you have to override the style of the TableCells too, because the overlap the TableRow border.
I have here a code sandbox that is by no means perfect, but should help you on the right track: https://codesandbox.io/s/material-demo-535zq?file=/demo.js
import { makeStyles } from '#material-ui/core/styles';
const useStyles = makeStyles(() => ({
rowStyle : {
padding: 10,
border: "1px solid red"
}
}));
const EnhancedTable = ()=>{
const classes = useStyles();
return(
<TableRow className={classes.rowStyle}/>
)
}

getting lat/long coordinates from firebase/firestore collection

im relative new to react native and firebase and it would be awesome if anyone could help me with this problem. currently when im adding new posts to my firebase collection i display all post with a flatlist and it works fine. but is it possible to get only the currentLatitude and currentLongitude for my markers? my target is to generate a new marker for each post.
Events = []
this.firestore.collection("Events").get().then(snapshot => {
snapshot.forEach(doc => {
Events.push(doc.data())
})
})
render() {
return (
<SafeAreaView style={{ flex: 1 }}>
<View style={{ flex: 1 }}>
<MapView
provider={PROVIDER_GOOGLE}
mapType='hybrid'
showsUserLocation style={{flex: 1}}>
<MapView.Marker
coordinate={{latitude: //currentLatitude,
longitude: //currntLongitude}}
title={("Test")}
description={("Test")}
/>
</MapView>
</View>
</SafeAreaView>
);
}
}
#DevAS thanks for your patience.. this was made from 3 different .js files.. but I don't now how to get it just into the map.js.
The final result should look something like this:
enter image description here
Everything except for the lat/lng cords are supposed to be in the callout-window.
Item.js:
import { Ionicons } from '#expo/vector-icons';
import React from 'react';
import { Image, StyleSheet, Text, View } from 'react-native';
import Fire from '../screens/Fire'
const profileImageSize = 36;
const padding = 12;
export default class Item extends React.Component {
state = {
user: {}
};
componentDidMount() {
const user = this.props.uid || Fire.shared.uid;
this.unsubscribe = Fire.shared.firestore
.collection("users")
.doc(user)
.onSnapshot(doc => {
this.setState({ user: doc.data() });
});
if (!this.props.imageWidth) {
// Get the size of the web image
Image.getSize(this.props.image, (width, height) => {
this.setState({ width, height });
});
}
}
componentWillUnmount() {
this.unsubscribe();
}
render() {
const { title, address, name, imageWidth, imageHeight, image, currentLatitude, currentLongitude } = this.props;
// Reduce the name to something
const imgW = imageWidth || this.state.width;
const imgH = imageHeight || this.state.height;
const aspect = imgW / imgH || 1;
return (
<View>
<Header image={{ uri: this.state.user.avatar }} name={this.state.user.name} />
<Image
resizeMode="contain"
style={{
backgroundColor: "#D8D8D8",
width: "100%",
aspectRatio: aspect
}}
source={{ uri: image }}
/>
<Metadata
name={this.state.user.name}
address={address}
title={title}
currentLongitude={currentLongitude}
currentLatitude={currentLatitude}
/>
</View>
);
}
}
const Metadata = ({ name, address, title, currentLongitude, currentLatitude}) => (
<View style={styles.padding}>
<IconBar />
<Text style={styles.text}>{name}</Text>
<Text style={styles.subtitle}>{address}</Text>
<Text style={styles.subtitle}>{title}</Text>
<Text style={styles.subtitle}>Lat: {currentLatitude}</Text>
<Text style={styles.subtitle}>Lng: {currentLongitude}</Text>
</View>
);
const Header = ({ name, image }) => (
<View style={[styles.row, styles.padding]}>
<View style={styles.row}>
<Image style={styles.avatar} source={image} />
<Text style={styles.text}>{name}</Text>
</View>
<Icon name="ios-more" />
</View>
);
const Icon = ({ name }) => (
<Ionicons style={{ marginRight: 8 }} name={name} size={26} color="black" />
);
const IconBar = () => (
<View style={styles.row}>
<View style={styles.row}>
<Icon name="ios-heart-empty" />
<Icon name="ios-chatbubbles" />
<Icon name="ios-send"/>
</View>
<Icon name="ios-bookmark" />
</View>
);
const styles = StyleSheet.create({
text: { fontWeight: "600" },
subtitle: {
opacity: 0.8
},
row: {
flexDirection: "row",
justifyContent: "space-between",
alignItems: "center"
},
padding: {
padding
},
avatar: {
aspectRatio: 1,
backgroundColor: "#D8D8D8",
borderWidth: StyleSheet.hairlineWidth,
borderColor: "#979797",
borderRadius: profileImageSize / 2,
width: profileImageSize,
height: profileImageSize,
resizeMode: "cover",
marginRight: padding
}
});
List.js
import React from 'react';
import { FlatList } from 'react-native';
import Footer from './Footer';
import Item from './Item';
class List extends React.Component {
renderItem = ({ item }) => <Item {...item} />;
keyExtractor = item => item.key;
render() {
const { onPressFooter, ...props } = this.props;
return (
<FlatList
keyExtractor={this.keyExtractor}
ListFooterComponent={footerProps => (
<Footer {...footerProps} onPress={onPressFooter} />
)}
renderItem={this.renderItem}
{...props}
/>
);
}
}
export default List;
FeedScreen.js
import firebase from "firebase";
import React, { Component } from "react";
import { LayoutAnimation, RefreshControl } from "react-native";
import List from "../components/List";
import Fire from "./Fire";
// Set the default number of images to load for each pagination.
const PAGE_SIZE = 5;
console.disableYellowBox = true;
export default class FeedScreen extends Component {
state = {
loading: false,
data: {}
};
componentDidMount() {
// Check if we are signed in...
if (Fire.shared.uid) {
// If we are, then we can get the first 5 posts
this.makeRemoteRequest();
} else {
// If we aren't then we should just start observing changes. This will be called when the user signs in
firebase.auth().onAuthStateChanged(user => {
if (user) {
this.makeRemoteRequest();
}
});
}
}
// Append the item to our states `data` prop
addPosts = posts => {
this.setState(previousState => {
let data = {
...previousState.data,
...posts
};
return {
data,
// Sort the data by timestamp
posts: Object.values(data).sort((a, b) => a.timestamp < b.timestamp)
};
});
};
// Call our database and ask for a subset of the user posts
makeRemoteRequest = async lastKey => {
// If we are currently getting posts, then bail out..
if (this.state.loading) {
return;
}
this.setState({ loading: true });
// The data prop will be an array of posts, the cursor will be used for pagination.
const { data, cursor } = await Fire.shared.getPaged({
size: PAGE_SIZE,
start: lastKey
});
this.lastKnownKey = cursor;
// Iteratively add posts
let posts = {};
for (let child of data) {
posts[child.key] = child;
}
this.addPosts(posts);
// Finish loading, this will stop the refreshing animation.
this.setState({ loading: false });
};
// Because we want to get the most recent items, don't pass the cursor back.
// This will make the data base pull the most recent items.
_onRefresh = () => this.makeRemoteRequest();
// If we press the "Load More..." footer then get the next page of posts
onPressFooter = () => this.makeRemoteRequest(this.lastKnownKey);
render() {
// Let's make everything purrty by calling this method which animates layout changes.
LayoutAnimation.easeInEaseOut();
return (
<List
refreshControl={
<RefreshControl
refreshing={this.state.loading}
onRefresh={this._onRefresh}
/>
}
onPressFooter={this.onPressFooter}
data={this.state.posts}
/>
);
}
}

How to view react native application database with tables

I'm creating a react native app. now I want to view my App database tables.
I don't know how many tables are in my SQLite database.
I am new in react native development & SQLite please help. to solve this issue
You can solve this problem through the Table View command. It can also be used to view data for that table.
/*Screen to view all the table*/
import React from 'react';
import { FlatList, Text, View } from 'react-native';
import { openDatabase } from 'react-native-sqlite-storage';
var db = openDatabase({ name: 'UserDatabase.db' });
export default class ViewAllTable extends React.Component {
constructor(props) {
super(props);
this.state = {
FlatListItems: [],
};
db.transaction(tx => {
tx.executeSql('SHOW TABLES', [], (tx, results) => {
var temp = [];
for (let i = 0; i < results.rows.length; ++i) {
temp.push(results.rows.item(i));
}
this.setState({
FlatListItems: temp,
});
});
});
}
ListViewItemSeparator = () => {
return (
<View style={{ height: 0.2, width: '100%', backgroundColor: '#808080' }} />
);
};
render() {
return (
<View>
<FlatList
data={this.state.FlatListItems}
ItemSeparatorComponent={this.ListViewItemSeparator}
keyExtractor={(item, index) => index.toString()}
renderItem={({item, index }) => (
<View key={item[index]} style={{ backgroundColor: 'white', padding: 20 }}>
<Text>Table: {item[index]}</Text>
</View>
)}
/>
</View>
);
}
}

Resources