autocomplete in react - javascript

Basically I have table when I click the row it opens the EditProperties dialog. The dialog has fields where you can add and delete fields.
The fields are dynamic so I dont need to repeat creating html it is based on the RegionalListData data.
Now each field the (EmailItem) on the dialog is an auto complete field where you can type and will pass values to the api and will return the result based on the api result.
The issue right now is when I type values on the input field it does not display my input and sometimes it displays , also when I type to the input field the value are sometimes directly erased and I dont know why.
Also when I select one item on the result it does not display on the input field.
My goal is to be able to type and search and it will call the api , it will update the call when I update my search input.
For example when I type Mark it should return all the results that matches mark. I should be able to search without it freezing.
Thanks for any help or idea , would be much appreacited.
#sample research object from the api
{
"isSuccess":true,
"message":"",
"data":[
{
"id":151,
"emailAddress":"mark.jasen#cushwar.com",
"firstName":"Mark",
"lastName":"Jasen"
},
{
"id":808,
"emailAddress":"mark.turmor#stream.com",
"firstName":"Mark",
"lastName":"Turmor"
},
{
"id":1228,
"emailAddress":"mark.logan#biias.com",
"firstName":"Mark",
"lastName":"Logan"
},
]
}
#Code snippet - this calls and opens the dialog
<EditProperties open={open} handleClose={handleClose} selectedRow={selectedRow} />
#EditProperties ts code
export const RegionalListData: IRegionalList[] = [
{
id: 4,
name: "Associate Director of Construction Ops",
column: "associateDirectorofConstructionOps",
emails: [
{
emailAddress: "associateDir#gmail.com",
firstName: "Associate",
lastName: "Director",
id: Math.floor(Math.random() * 999),
fetching: false,
},
],
},
{
id: 5,
name: "CAM Manager",
column: "camManager",
emails: [
{
emailAddress: "associateDir#gmail.com",
firstName: "Associate",
lastName: "Director",
id: Math.floor(Math.random() * 999),
fetching: false,
},
],
},
{
id: 6,
name: "CAO-Chief Administrative Officer",
column: "caoChiefAdministrativeOfficer",
emails: [
{
emailAddress: "associateDir#gmail.com",
firstName: "Associate",
lastName: "Director",
id: Math.floor(Math.random() * 999),
fetching: false,
},
],
},
];
type InitialReqPaylod = {
accountId: number;
regionalRoleUserDto: IRegional;
};
type IData = {
regionName: string;
marketName: string;
subRegionName: string;
};
type IEmail = {
emailAddress: string;
firstName: string;
id: number;
lastName: string;
};
const EditProperties: FC<EditPropertiesProps> = ({
open,
handleClose,
selectedRow,
}) => {
const dispatch = useAppDispatch();
const [isEmailOpen, setOpenEmail] = useState(false);
const [fetching, setFetching] = useState(false);
const [RegionalList, setRegionalList] = useState<IRegionalList[]>(
RegionalListData
);
const [data, setData] = useState<IData>({
regionName: "",
marketName: "",
subRegionName: "",
});
const [regionalId, setRegionalId] = useState<number | null>(null);
const [emailCurrentIndex, setEmailCurrentIndex] = useState<number | null>(
null
);
const [selectedEmailId, setSelectedEmailId] = useState<number | null>(null);
const { isSuccess } = useAppSelector((state) => state.yardUser);
const { isSaveSuccess } = useAppSelector((state) => state.region);
const email = useAppSelector((state) => state.yardUser);
const [emailOptions, setEmailOptions] = useState<IEmail[]>([]);
const emailList = email.data ? email.data.data : [];
useEffect(() => {
if (selectedRow) {
setData({
regionName: selectedRow["regionName"],
marketName: selectedRow["marketName"],
subRegionName: selectedRow["subRegionName"],
});
let regional = [...RegionalList];
for (const k in selectedRow) {
regional.map((prop: IRegionalList) => {
if (prop.column === k) {
prop.emails = selectedRow[k] ? selectedRow[k] : [];
}
});
}
setRegionalList(regional);
}
}, [selectedRow]);
const [maxWidth, setMaxWidth] = React.useState<DialogProps["maxWidth"]>("md");
const fetchEmailResult = React.useMemo(
() =>
throttle(
(event: any, callback: (results: IEmail[]) => void) => {
const payload: IYardUserRequestPayload | InitialReqPaylod = {
accountId: 1,
searchString: event.target.value,
};
fetch(
`https://jsonplaceholder.typicode.com/users?email=${event.target.value}`
)
.then((res) => res.json())
.then((res) => res.data ? callback(res.data.slice(0, 10)) : callback([]))
},
200
),
[]
);
const emailOnChange = (event: any, regionalId: number, index: number, emailId: number) => {
setRegionalId(regionalId);
setEmailCurrentIndex(index);
setSelectedEmailId(emailId);
fetchEmailResult(event,(results: IEmail[]) => {
console.log('results' , results)
if (results.length) setEmailOptions(results);
});
};
useEffect(() => {
if (isSaveSuccess) {
handleClose();
}
}, [isSaveSuccess]);
useEffect(() => {
if (isSuccess) {
setFetching(false);
}
}, [isSuccess]);
const addEmail = (id: number) => {
setRegionalList((list) =>
list.map((item) => {
if (item.id === id) {
return {
...item,
emails: [
...item.emails,
{
emailAddress: "",
firstName: "",
lastName: "",
id: Math.floor(Math.random() * 999),
fetching: false,
},
],
};
}
return item;
})
);
};
const deleteEmail = (email: IEmail, regionId: number) => {
const regionalListCopy = [...RegionalList].map((prop: IRegionalList) => {
if (prop.id === regionId) {
return {
...prop,
emails: prop.emails.filter((prop) => prop.id !== email.id),
};
}
return { ...prop };
});
setRegionalList(regionalListCopy);
};
const setOnChangeOption = (email) => {
setSelectedEmailId(null);
setRegionalList((list) =>
list.map((item) => {
if (item.id === regionalId) {
return {
...item,
emails: [
...item.emails.map((prop) => {
return {
...prop,
...email,
};
}),
],
};
}
return item;
})
);
};
const EmailItem = ({ email, mIndex, prop }) => (
<>
<div style={{ display: "block" }} key={email.id}>
<div
style={{
display: "flex",
justifyContent: "space-between",
alignItems: "center",
marginTop: 15
}}
>
<Autocomplete
options={emailOptions}
getOptionLabel={(option: IEmail) => option.emailAddress}
onInputChange={($event) => emailOnChange($event, prop.id, mIndex, email.id)}
onChange={($event, value) => setOnChangeOption(value)}
fullWidth
open={email.id === selectedEmailId}
renderInput={(params) => (
<TextField size="small" {...params} variant="standard" />
)}
renderOption={(props, option) => {
return (
<Box component="li" {...props}>
{option.emailAddress}
</Box>
);
}}
/>
<DeleteIcon
style={{ color: "red", cursor: "pointer" }}
onClick={() => deleteEmail(email, prop.id)}
/>
</div>
<div
style={{
fontSize: ".8em",
display: "flex",
justifyContent: "space-between",
}}
>
<span style={{ paddingTop: 5 }}>
Email : {email.emailAddress}
Full Name: {email.firstName} {email.lastName}
</span>
{/* <span style={{ paddingRight : 40 }}>{fetching ? "Fetching...." : null}</span> */}
</div>
</div>
</>
);
return (
<Dialog
maxWidth={maxWidth}
open={open}
onClose={handleClose}
aria-labelledby="alert-dialog-title"
aria-describedby="alert-dialog-description"
>
<DialogTitle id="alert-dialog-title">Edit</DialogTitle>
<DialogContent>
<Card sx={{ minWidth: 275 }} style={{ padding: 20 }}>
<div>
<span>Sub-Region (Sub-Division)</span>
<Divider style={{ marginTop: 10 }} />
<FormControl sx={{ mt: 2, minWidth: 720 }}>
<TextField
label="Region (Division)"
variant="filled"
value={data.regionName}
/>
</FormControl>
</div>
<div style={{ marginTop: 10 }}>
<span>Sub-Region (Sub-Division)</span>
<Divider style={{ marginTop: 10 }} />
<FormControl sx={{ mt: 2, minWidth: 720 }}>
<TextField
label="Sub-Region (Sub-Division)"
variant="filled"
value={data.subRegionName}
/>
</FormControl>
</div>
<div style={{ marginTop: 10 }}>
<span>Market</span>
<Divider style={{ marginTop: 10 }} />
<FormControl sx={{ mt: 2, minWidth: 720 }}>
<TextField
label="Market"
variant="filled"
value={data.marketName}
/>
</FormControl>
</div>
</Card>
{RegionalList.map((prop: IRegionalList, index: number) => (
<Card
sx={{ minWidth: 275 }}
style={{ overflow: "visible", padding: 20, marginTop: 20 }}
key={prop.id}
>
<div style={{ display: "flex", alignItems: "center" }}>
{prop.name}*{" "}
<AddIcon
style={{ marginLeft: 5, cursor: "pointer" }}
onClick={() => addEmail(prop.id)}
/>
</div>
<Divider style={{ marginTop: 10 }} />
{prop.emails.map((email: IEmail, mIndex: number) => (
<EmailItem
key={email.id}
prop={prop}
email={email}
mIndex={mIndex}
/>
))}
</Card>
))}
</DialogContent>
<DialogActions
style={{ marginTop: "20px", marginRight: "20px", marginBottom: "20px" }}
>
<Button onClick={handleClose}>Cancel</Button>
<Button variant="contained" onClick={() => saveChanges()} autoFocus>
Save Changes
</Button>
</DialogActions>
</Dialog>
);
};
export default EditProperties;

Related

React: How to convert MUI data table to collapsible MUI table

I am trying to to make a MUI data table to be collapsible but I can't make it. So I have working demo of collapsible MUI table here https://codesandbox.io/s/19r60?file=/src/ExpandableRowTable.js
How can I transform the existing non collapsible MUI data table to collapsible MUI table?
Here is my code
TripsTable.js (minimal code)
function TripsTable({ data, userSettings, refetchData, ...props }) {
const classes = useStyles();
const { t } = useTranslation();
const isKm = userSettings.metrics === Metrics.KM;
const columns = [
{
field: "collision",
headerName: " ",
flex: 0.7,
disableColumnMenu: true,
renderCell: (params) => (
<span className={classes.iconsCell}>
{params.row.events
.map((e) => e.event_type_name)
.includes("COLLISION") && (
<img src={collision} alt="" title="Collision" />
)}
{params.row.isBeaconTagged && (
<img src={BeaconsIcon} alt="" title="Beacon" />
)}
{params.row.isBluetoothTagged && (
<img src={BluetoothIcon} alt="" title="Bluetooth" />
)}
</span>
),
},
{
field: "tripStartTimeStr",
headerName: t("date"),
flex: 1.5,
disableColumnMenu: true,
sortComparator: (v1, v2, p1, p2) => new Date(v1) - new Date(v2),
renderCell: (params) => (
<pre>
<span
style={{
marginLeft: 0,
padding: "5px 7px",
borderRadius: 7,
color: params.row.score < 72 ? "#fff" : "",
fontWeight: "normal",
backgroundColor:
params.row.score < 72 ? "#F44138" : "transparent",
}}
>
{params.value}
</span>
</pre>
),
},
{
field: "tripType",
headerName: t("tripType"),
flex: 1.4,
disableColumnMenu: true,
hide: isHiddenTripType,
renderCell: (params) => (
<TripTypeSelector
type={params.value}
tripId={params.row.tripId}
refetchTrips={refetchData}
/>
),
},
{
field: "drivingTimeSeconds",
headerName: t("drivingTime"),
flex: 1.1,
disableColumnMenu: true,
sortComparator: (v1, v2, p1, p2) =>
p1.api.getRow(p1.id).drivingTimeSeconds -
p2.api.getRow(p2.id).drivingTimeSeconds,
renderCell: (params) => (
<span>
{Math.round(params.value / 60)} {t("minutes")}
</span>
),
},
{
field: "distanceDriven",
headerName: t(isKm ? "kilometersDriven" : "milesDriven"),
flex: 1.1,
disableColumnMenu: true,
sortComparator: (v1, v2, p1, p2) =>
p1.api.getRow(p1.id).distanceDriven -
p2.api.getRow(p2.id).distanceDriven,
valueFormatter: (params) =>
`${params.value.toFixed(2)} ${t(isKm ? "km" : "mi")}`,
},
...DrivingBehaviourKeysArr.map((evnt) => ({
field: evnt,
headerName: t(evnt),
flex: 0.9,
disableColumnMenu: true,
renderCell: eventScoreCell,
})),
{
field: "fleetId",
headerName: t("Fleet"),
flex: 1.1,
disableColumnMenu: true,
},
{
field: "category",
headerName: t("category"),
flex: 1.1,
disableColumnMenu: true,
sortComparator: (v1, v2, param1, param2) =>
param1.api.getCellValue(param1.id, "score") -
param2.api.getCellValue(param2.id, "score"),
renderCell: (params) => (
<span style={{ color: getCategoryColor(params.row.score) }}>
{params.value}
</span>
),
},
{
field: "score",
headerName: t("score"),
flex: 1,
disableColumnMenu: true,
},
];
const [isVisible, setIsVisible] = useState(true);
const { fleetId, driverId } = useParams();
const { tripId } = useQuery();
const history = useHistory();
const ref = useRef();
const filteredData = isOnlyBusinessTrips
? data.filter((row) => row.tripType == TripTypes.BUSINESS)
: data;
const trip = useMemo(
() => filteredData.find((t) => t.tripId === tripId),
[filteredData, tripId]
);
useEffect(() => {
setTimeout(() => ref.current?.scrollIntoView({ behavior: "smooth" }), 100);
}, [isVisible, trip]);
const handleSelectTrip = useCallback(
(row) => {
if (row.id !== tripId) {
history.push(FrontendRoutes.DRIVER_OVERVIEW(fleetId, driverId, row.id));
setIsVisible(true);
} else {
setIsVisible(!isVisible);
}
},
[isVisible, driverId, tripId]
);
const rows = useMemo(
() => filteredData.map((d) => ({ ...d, id: d.tripId })),
[filteredData]
);
// console.log("data", data);
return (
<ChartWrapper {...props}>
<div className={classes.root}>
<DataTable
selectionModel={tripId ? [tripId] : undefined}
rows={rows}
columns={columns}
onCellClick={handleSelectTrip}
/>
</div>
{trip && isVisible && (
<DriverTripOverview trip={trip} userSettings={userSettings} />
)}
<span ref={ref} />
</ChartWrapper>
);
}
export default memo(TripsTable);
How can show DriverTripOverview component below every clicked table row?

Onchange stops for every letter I type

I am trying to have a single onChange event for each element that is rendered with the map function. The problem is that for each letter that I write, it is as if the execution stops, preventing me from writing freely and seeing the changes I am making in the text field in the console.
Here you can see the error: https://codesandbox.io/s/tender-wu-kuzqd
const options = [
{ id: 1, hour: 0, minute: 0, enrollment: '', value: 'ac.terapeutico', label: 'Ac. Terapéutico', color: getRandomColor() },
{ id: 2, hour: 0, minute: 0, enrollment: '', value: 'kinesiologia', label: 'Kinesiología', color: getRandomColor() },
{ id: 3, hour: 0, minute: 0, enrollment: '', value: 'oncologia', label: 'Oncología', color: getRandomColor() }
];
const Form = () => {
const [selectedSpeciality, setSelectedSpeciality] = useState(null);
const handleChangeEnrollment = (value, id) => {
let index = selectedSpeciality.findIndex(el => el.id === id);
const data = [...selectedSpeciality];
data[index].enrollment = value;
setSelectedSpeciality(data);
}
return (
<Grid container spacing={2}>
<Grid item xs={12}>
<Select
closeMenuOnSelect={true}
isMulti
options={options}
styles={colourStyles}
value={selectedSpeciality}
onChange={setSelectedSpeciality}
placeholder='Seleccione especialidades'
noOptionsMessage={() => "No hay más opciones"}
/>
</Grid>
{selectedSpeciality &&
selectedSpeciality.map(el => (
<Fragment key={uuid()}>
<Grid item xs={6}>
<TextField
fullWidth
InputLabelProps={{
shrink: true,
}}
value={el.enrollment}
onChange={(e) => handleChangeEnrollment(e.target.value, el.id)}
label={`MATRÍCULA ${el.label.toUpperCase()}`}
/>
</Grid>
</Fragment>
))
}
{console.log(selectedSpeciality)}
</Grid>
);
}
The problem is that you are using Fragment with uuid, which create a new instance at each render.
This results in rendering the whole part again and losing focus.
You need to remove Fragment or use any other consistent key value for each element in map.
Without Fragment
See: https://codesandbox.io/s/lucid-field-crolh?file=/src/App.js
import React, { useState, Fragment } from "react";
import uuid from "react-uuid";
import styled from "styled-components";
import Select from "react-select";
import { Grid, TextField, Box } from "#material-ui/core";
export const StyleWrapper = styled.div`
.MuiInputBase-root {
font-size: 24px;
font-weight: 600;
color: #061655;
}
`;
const dot = (color = "#ccc") => ({
alignItems: "center",
display: "flex",
":before": {
backgroundColor: color,
borderRadius: 10,
content: '" "',
display: "block",
marginRight: 4,
marginLeft: 8,
height: 10,
width: 10
}
});
const colourStyles = {
control: (styles) => ({ ...styles, backgroundColor: "white" }),
option: (styles, { data, isDisabled, isFocused, isSelected }) => {
return {
...styles,
backgroundColor: isDisabled
? null
: isSelected
? data.color
: isFocused
? "000000"
: null,
color: isDisabled
? "#ccc"
: isSelected
? "000000" > 2
? "white"
: "black"
: "000000",
cursor: isDisabled ? "not-allowed" : "default",
":active": {
...styles[":active"],
backgroundColor: !isDisabled && (isSelected ? "000000" : "000000")
},
borderRadius: "10px"
};
},
placeholder: (styles) => ({ ...styles, ...dot() }),
multiValue: (styles, { data }) => ({
...styles,
...dot(data.color),
borderRadius: "40px"
}),
multiValueLabel: (styles) => ({
...styles,
color: "#061655",
fontWeight: 500
}),
multiValueRemove: (styles, { data }) => ({
...styles,
color: "#061655",
padding: "8px 8px 8px 4px",
":hover": {
backgroundColor: "#transparent",
color: "#061655",
cursor: "pointer",
borderRadius: "0px 40px 40px 0px"
}
})
};
const FormAddProfessional = (props) => {
const [selectedSpeciality, setSelectedSpeciality] = useState(null);
const optionsSpeciality = [
{
id: 1,
hour: 0,
minute: 0,
enrollment: "",
value: "ac.terapeutico",
label: "Ac. Terapéutico"
},
{
id: 2,
hour: 0,
minute: 0,
enrollment: "",
value: "kinesiologia",
label: "Kinesiología"
},
{
id: 3,
hour: 0,
minute: 0,
enrollment: "",
value: "oncologia",
label: "Oncología"
}
];
const handleChangeEnrollment = (value, id) => {
let index = selectedSpeciality.findIndex((el) => el.id === id);
const data = [...selectedSpeciality];
data[index].enrollment = value;
setSelectedSpeciality(data);
};
return (
<div style={{ width: "100%" }}>
<div style={{ paddingLeft: 4 }}>
<Box borderLeft={1} borderColor="#EBEBEB" style={{ padding: 12 }}>
<Grid container spacing={2}>
<Grid item xs={12}>
<Select
closeMenuOnSelect={true}
isMulti
options={optionsSpeciality}
styles={colourStyles}
value={selectedSpeciality}
onChange={setSelectedSpeciality}
placeholder="Seleccione especialidades"
noOptionsMessage={() => "No hay más opciones"}
/>
</Grid>
{selectedSpeciality &&
selectedSpeciality.map((el) => (
<Grid item xs={6}>
<TextField
fullWidth
InputLabelProps={{
shrink: true
}}
value={el.enrollment}
onChange={(e) =>
handleChangeEnrollment(e.target.value, el.id)
}
label={`MATRÍCULA ${el.label.toUpperCase()}`}
/>
</Grid>
))}
{console.log(selectedSpeciality)}
</Grid>
</Box>
</div>
</div>
);
};
export default FormAddProfessional;
With different consistent key value
See: https://codesandbox.io/s/angry-jang-8w004?file=/src/App.js:0-4014
import React, { useState, Fragment } from "react";
import uuid from "react-uuid";
import styled from "styled-components";
import Select from "react-select";
import { Grid, TextField, Box } from "#material-ui/core";
export const StyleWrapper = styled.div`
.MuiInputBase-root {
font-size: 24px;
font-weight: 600;
color: #061655;
}
`;
const dot = (color = "#ccc") => ({
alignItems: "center",
display: "flex",
":before": {
backgroundColor: color,
borderRadius: 10,
content: '" "',
display: "block",
marginRight: 4,
marginLeft: 8,
height: 10,
width: 10
}
});
const colourStyles = {
control: (styles) => ({ ...styles, backgroundColor: "white" }),
option: (styles, { data, isDisabled, isFocused, isSelected }) => {
return {
...styles,
backgroundColor: isDisabled
? null
: isSelected
? data.color
: isFocused
? "000000"
: null,
color: isDisabled
? "#ccc"
: isSelected
? "000000" > 2
? "white"
: "black"
: "000000",
cursor: isDisabled ? "not-allowed" : "default",
":active": {
...styles[":active"],
backgroundColor: !isDisabled && (isSelected ? "000000" : "000000")
},
borderRadius: "10px"
};
},
placeholder: (styles) => ({ ...styles, ...dot() }),
multiValue: (styles, { data }) => ({
...styles,
...dot(data.color),
borderRadius: "40px"
}),
multiValueLabel: (styles) => ({
...styles,
color: "#061655",
fontWeight: 500
}),
multiValueRemove: (styles, { data }) => ({
...styles,
color: "#061655",
padding: "8px 8px 8px 4px",
":hover": {
backgroundColor: "#transparent",
color: "#061655",
cursor: "pointer",
borderRadius: "0px 40px 40px 0px"
}
})
};
const FormAddProfessional = (props) => {
const [selectedSpeciality, setSelectedSpeciality] = useState(null);
const optionsSpeciality = [
{
id: 1,
hour: 0,
minute: 0,
enrollment: "",
value: "ac.terapeutico",
label: "Ac. Terapéutico"
},
{
id: 2,
hour: 0,
minute: 0,
enrollment: "",
value: "kinesiologia",
label: "Kinesiología"
},
{
id: 3,
hour: 0,
minute: 0,
enrollment: "",
value: "oncologia",
label: "Oncología"
}
];
const handleChangeEnrollment = (value, id) => {
let index = selectedSpeciality.findIndex((el) => el.id === id);
const data = [...selectedSpeciality];
data[index].enrollment = value;
setSelectedSpeciality(data);
};
return (
<div style={{ width: "100%" }}>
<div style={{ paddingLeft: 4 }}>
<Box borderLeft={1} borderColor="#EBEBEB" style={{ padding: 12 }}>
<Grid container spacing={2}>
<Grid item xs={12}>
<Select
closeMenuOnSelect={true}
isMulti
options={optionsSpeciality}
styles={colourStyles}
value={selectedSpeciality}
onChange={setSelectedSpeciality}
placeholder="Seleccione especialidades"
noOptionsMessage={() => "No hay más opciones"}
/>
</Grid>
{selectedSpeciality &&
selectedSpeciality.map((el) => (
<Fragment key={el.value}>
<Grid item xs={6}>
<TextField
fullWidth
InputLabelProps={{
shrink: true
}}
value={el.enrollment}
onChange={(e) =>
handleChangeEnrollment(e.target.value, el.id)
}
label={`MATRÍCULA ${el.label.toUpperCase()}`}
/>
</Grid>
</Fragment>
))}
{console.log(selectedSpeciality)}
</Grid>
</Box>
</div>
</div>
);
};
export default FormAddProfessional;

How do i switch elements from object, when there are no initial state in the first place?

a guy helped me with this code
import React, { useEffect, useState } from "react";
import _ from "lodash";
// const SeleccionClientes = "";
const items = [
{
client: "Microsoft",
idClient: 0,
idProjectType: 1,
projectType: "traditional",
title: "React Native App"
},
{
client: "Amazon",
idClient: 1,
idProjectType: 1,
projectType: "traditional",
title: "ServerSide OPS"
},
{
client: "KFC",
idClient: 2,
idProjectType: 4,
projectType: "traditional",
title: "QR Reader"
},
{
client: "KFC",
idClient: 2,
idProjectType: 1,
projectType: "traditional",
title: "React Native App"
},
{
client: "KFC",
idClient: 2,
idProjectType: 1,
projectType: "traditional",
title: "React KKL"
},
{
client: "PEICI",
idClient: 3,
idProjectType: 1,
projectType: "traditional",
title: "KuKluxKlan"
}
];
export default function ListView() {
const [list, setList] = useState(items);
const [idClient, setIdClient] = useState(2);
const displayProjectsForClient = idClient => {
return list.filter(item => item.idClient === idClient);
};
const displayedProjects = displayProjectsForClient(idClient);
// equivalent to componentDidMount()
useEffect(() => {
setList(displayedProjects);
}, []);
const updateFav = (val, ind) => {
const tempData = _.cloneDeep(list);
tempData[ind].fav = val;
setList(tempData);
};
const favItems = _.filter(list, item => item.fav);
const finalObject = { [new Date().toISOString()]: favItems };
return (
<div>
Selected Client: "KFC"
<br />
Add Favorite Projects:
{displayedProjects.map((item, index) => {
return (
<div
key={index}
style={{ margin: "5px", padding: "5px", background: "#D6D6D6" }}
>
<div>{item.title}</div>
{`Project ID ${item.idProjectType}`}
<input
type="checkbox"
value={item.fav}
onChange={e => updateFav(e.target.checked, index)}
/>
</div>
);
})}
<div>
Active projects (final object): <br />
{JSON.stringify(finalObject, null, 2)}
</div>
</div>
);
}
instead of input checkbox, i'm using the react-native-elements switch, but is not working, i'm assuming is due to a non existing fav inside the item object
this is my code
<FlatList
data={dataSource}
renderItem={({item, index}) => (
<ListItem
containerStyle={{backgroundColor: '#fafafa', width: wp('87.1%'), height: 64, alignItems: 'center', justifyContent: 'center', alignSelf: 'center', marginTop: hp('2.8%'), paddingHorizontal: 0}}
topDivider={false}
bottomDivider={true}
titleStyle={{
marginLeft: 0,
fontSize: rfv(16),
fontWeight: "normal",
fontStyle: "normal",
textAlign: "left",
color: "#707070"
}}
subtitleStyle={{
marginLeft: 0,
fontSize: rfv(14),
fontWeight: "normal",
fontStyle: "normal",
textAlign: "left",
color: "#c4c4c4"
}}
title={`${item.title}`}
subtitle={`ID ${item.idCliente}`}
switch={{
trackColor: { false: "#767577", true: "#81b0ff" },
thumbColor: item.fav == true ? "#1062cc" : "#f4f3f4",
ios_backgroundColor: "#9e9e9e",
value: item.fav == undefined ? false : true,
onValueChange: () => {e => console.log(updateFav(e.target.checked == undefined ? false : true, index))}
}}
/>
)}
/>
the idea is to list the projects, which is doing, but when i click on a switch, it creates a whole new object based on that "selection", problem is, the switches are getting to the original position immediately,
forgot to mention, this is the function
const updateFav = (value, index) => {
const tempData = _.cloneDeep(dataSource);
tempData[index].fav = value;
setDataSource(tempData);
};
const favItems = _.filter(dataSource, item => item.fav);
You are using a mixture of React (Html) and React native thats the problem. You will have to change your Switch like this for the function to work. And no need to check for true false as well.
switch={{
trackColor: { false: "#767577", true: "#81b0ff" },
thumbColor: item.fav == true ? "#1062cc" : "#f4f3f4",
ios_backgroundColor: "#9e9e9e",
value: item.fav,
onValueChange: () => {updateFav(!item.fav, index)}
}}

ClusteredMapView - Android - Continuously re-rendering and making the map very slow. Works fine in iOS

Does anyone know off-hand if react-native-maps-super-cluster is just kind of slow on android, or if there is something in my code that is making it slow? It works fine on iOS, and then I tried on Android, and now it hardly responds. It will keep flipping between zoom levels and regions, etc.
Here is what I have
renderMap = () => {
var { width, height } = Dimensions.get('window');
return (
<View style={FULL}>
{/* Cluster Map Example */}
{!this.state.connection && (
<Text
style={{
backgroundColor: palette.angry,
color: palette.offWhite,
justifyContent: 'center',
alignContent: 'center',
textAlign: 'center',
fontWeight: 'bold'
}}
>
Bad Connection
</Text>
)}
<ClusteredMapView
radius={100}
edgePadding={{ top: 10, left: 30, bottom: 10, right: 30 }}
style={{
flex: 1,
width: width,
height: height
}}
data={this.state.markers}
renderMarker={this.renderMarker}
renderCluster={this.renderCluster}
initialRegion={this.getInitialState()}
region={this.state.region}
onRegionChangeComplete={this.onRegionChange}
ref={(ref) => (this.mapView = ref)}
clusterPressMaxChildren={10000}
>
{/*
Markers rendered as children of ClusteredMapView are not taken in account by the clustering feature,
they will just act as they were rendered within a normal react-native-maps instance
<Marker coordinate={{ latitude: 44.710968, longitude: 10.640131 }} pinColor={'#65bc46'} />
*/}
</ClusteredMapView>
<Modal
isVisible={false}
onBackdropPress={this.toggleModal}
onSwipeComplete={this.toggleModal}
swipeDirection='left'
>
<View style={MODAL}>
<Text style={TEXT}>I am the modal content!</Text>
</View>
</Modal>
<ActionSheet
styles={actionSheetStyles}
ref={(o) => (this.ActionSheet = o)}
title={this.state.actionSheetTitle}
options={[ 'Cancel', 'Detail', 'Directions', 'Remove Donor' ]}
cancelButtonIndex={0}
onPress={(index) => {
switch (index) {
case 1:
this.goToDonorDetail();
break;
case 2:
console.tron.log('Directions');
break;
case 3:
this.removeDonor();
break;
default:
console.tron.log('Default');
}
}}
/>
</View>
);
};
renderMarker = (pin) => {
console.tron.log('Rendering Marker');
let index = this.state.markers.findIndex((lead) => lead.key === pin.key);
if (index >= 0) {
return (
<Marker
identifier={`pin-${pin.id}`}
key={pin.key}
//icon={mapMarker}
radius={70}
coordinate={pin.location}
pinColor={
pin.memberType === 'New Business' ? (
palette.angry
) : pin.memberType === 'Rejoiner' ? (
palette.green
) : (
palette.blue
)
}
onPress={() => this.markerOnPress(pin)}
calloutOffset={{ x: 0, y: 0 }}
>
{/*<Image source={require('./Map-Marker.png')} style={{ height: 35, width: 35 }} />*/}
<Callout
alphaHitTest
tooltip={false}
onPress={(e) => {
/*if (
e.nativeEvent.action === 'marker-inside-overlay-press' ||
e.nativeEvent.action === 'callout-inside-press'
) {
return;
}*/
this.showActionSheet(pin);
}}
style={styles.customView}
>
<View style={MODAL}>
<Text>
{pin.firstName} {pin.lastName}
</Text>
<Text>{pin.companyName}</Text>
<Text>{pin.address}</Text>
<Text>
{pin.city}, {pin.state} {pin.zip}
</Text>
</View>
</Callout>
</Marker>
);
} else return null;
};
renderCluster = (cluster, onPress) => {
const pointCount = cluster.pointCount,
coordinate = cluster.coordinate,
clusterId = cluster.clusterId;
const clusteringEngine = this.mapView.getClusteringEngine(),
clusteredPoints = clusteringEngine.getLeaves(clusterId, pointCount);
let rejoiners = [];
let leads = [];
let renewals = [];
clusteredPoints.map((point) => {
let item = point.properties.item;
if (item.opportunityType) {
if (item.opportunityType === 'Rejoiner') {
rejoiners.push(item);
} else if (item.opportunityType === 'Renewal') {
renewals.push(item);
}
} else {
leads.push(item);
}
});
let keys = [ 'rejoiners', 'renewals', 'leads' ];
let values = [ rejoiners.length, renewals.length, leads.length ];
const colors = [ 'green', 'blue', 'red' ];
const data = keys.map((key, index) => {
return {
key,
value: values[index],
svg: { fill: colors[index] }
//arc: { outerRadius: 80 + '%', padAngle: label === key ? 0.1 : 0 },
//onPress: () => this.setState({ selectedSlice: { label: key, value: values[index] } })
};
});
/*<PieChart style={{ height: 200 }} outerRadius={'80%'} innerRadius={'15%'} data={data} />*/
return (
<Marker identifier={`cluster-${clusterId}`} coordinate={coordinate} onPress={onPress}>
<View
style={{
flexDirection: 'row',
width: 100,
height: 100
}}
>
<Svg width={100} height={100}>
<PieChart style={{ height: 100 }} outerRadius={'100%'} innerRadius={'0%'} data={data} />
<View
style={{
height: 100,
width: 100,
position: 'absolute',
justifyContent: 'center',
alignItems: 'center'
}}
>
<Text
style={{
color: 'white',
fontWeight: 'bold',
textAlign: 'center',
textAlignVertical: 'center'
}}
>
{clusteredPoints.length}
</Text>
</View>
</Svg>
</View>
</Marker>
);
};
componentDidMount = async () => {
console.tron.log('Component Mounting');
this.subs = [ this.props.navigation.addListener('didFocus', () => this.componentDidFocus()) ];
NetInfo.fetch().then((state) => {
console.tron.log('Connection type', state.type);
console.tron.log('Is connected?', state.isConnected);
});
const unsubscribe = NetInfo.addEventListener((state) => {
console.log('Connection type', state.type);
console.log('Is connected?', state.isConnected);
console.tron.log('Connected to Internet: ', state.isInternetReachable);
if (!state.isConnected || !state.isInternetReachable) {
this.setState({ connection: false });
} else {
this.setState({ connection: true });
}
});
unsubscribe();
/**
* { location: { latitude: 41.8962667,longitude: 11.3340056 } }
*/
const { filterStore, donorStore, navigation, opportunityStore } = this.props;
navigation.setParams({ mapIcon: this.mapIcon, navigateToFilters: () => this.navigateToFilters() });
await donorStore.getLeads().catch((e) => console.tron.log(e.message));
await opportunityStore.getOpportunities().catch((e) => console.tron.log(e.message));
let donors = filterStore.filteredLeads;
let rejoiners = opportunityStore.allRejoiners;
let renewals = opportunityStore.allRenewals;
this.setMarkers(donors, rejoiners, renewals);
this.setState({ region: this.getInitialState(), mounted: true });
};
setMarkers = (donors, rejoiners, renewals) => {
const { filterStore } = this.props;
let filtered = filterStore.filteredLeads;
try {
//filtered.forEach((donor) => console.tron.log(donor));
} catch (e) {
console.tron.log(e.message);
}
let markers = [];
if (donors && donors.length > 0) {
donors.forEach((donor, index) => {
markers.push({
id: donor.id,
key: donor.key,
location: {
latitude: donor.location._lat,
longitude: donor.location._long
},
index: index,
memberType: donor.memberType,
companyName: donor.companyName,
firstName: donor.firstName,
lastName: donor.lastName,
address1: donor.votingAddress.address1,
address2: donor.votingAddress.address2,
city: donor.votingAddress.city,
state: donor.votingAddress.state,
zip: donor.votingAddress.zip
});
});
}
if (rejoiners && rejoiners.length > 0) {
rejoiners.forEach((rejoiner, index) => {
let donor = rejoiner.donor;
markers.push({
...rejoiner,
id: donor.id,
location: {
latitude: donor.location._lat,
longitude: donor.location._long
},
index: index,
memberTypeDonor: donor.memberType,
companyName: donor.companyName,
firstName: donor.firstName,
lastName: donor.lastName,
address1: donor.votingAddress.address1,
address2: donor.votingAddress.address2,
city: donor.votingAddress.city,
state: donor.votingAddress.state,
zip: donor.votingAddress.zip,
memberType: 'Rejoiner'
});
});
}
if (renewals && renewals.length > 0) {
renewals.forEach((renewal, index) => {
let donor = renewal.donor;
markers.push({
...renewal,
id: donor.id,
location: {
latitude: donor.location._lat,
longitude: donor.location._long
},
index: index,
memberTypeDonor: donor.memberType,
companyName: donor.companyName,
firstName: donor.firstName,
lastName: donor.lastName,
address1: donor.votingAddress.address1,
address2: donor.votingAddress.address2,
city: donor.votingAddress.city,
state: donor.votingAddress.state,
zip: donor.votingAddress.zip,
memberType: 'Renewal'
});
});
}
this.setState({ markers });
};
I know there are some optimizations that I can make. I tried to make them in a previous attempt to fix the bouncing around, but eventually just reverted my code to try again, and have no included the improvements again. Any help is appreciated.
Updated ClusterMarker to be its own class and added tracksViewChanges.
export class ClusterMarker extends React.Component<ClusterMarkerProps, {}> {
state = {
tracksViewChanges: true
};
componentWillReceiveProps(nextProps: any) {
console.tron.log('Component Will Receive Props');
if (!isEqual(this.props, nextProps)) {
this.setState(() => ({
tracksViewChanges: true
}));
}
}
componentDidUpdate() {
console.tron.log('Component Did update');
if (this.state.tracksViewChanges) {
this.setState(() => ({
tracksViewChanges: false
}));
}
}
render() {
let { clusterId, onPress, coordinate, data, clusteredPoints } = this.props;
return (
<Marker
identifier={`cluster-${clusterId}`}
coordinate={coordinate}
onPress={onPress}
tracksViewChanges={this.state.tracksViewChanges}
>
<View
style={{
flexDirection: 'row',
width: 100,
height: 100
}}
>
<Svg width={100} height={100}>
<PieChart style={{ height: 100 }} outerRadius={'100%'} innerRadius={'0%'} data={data} />
<View
style={{
height: 100,
width: 100,
position: 'absolute',
justifyContent: 'center',
alignItems: 'center'
}}
>
<Text
style={{
color: 'white',
fontWeight: 'bold',
textAlign: 'center',
textAlignVertical: 'center'
}}
>
{clusteredPoints.length}
</Text>
</View>
</Svg>
</View>
</Marker>
);
}
}
I am still having some issues with this. I am watching my console and it seems to be re-rendering constantly. The more zoomed in I am, the more it jumps around. It seems to be moving to different regions constantly, but I can't tell why it is doing that. Did I implement the tracksViewChanges properly?

Delete List Item on right swipe react-native

// Here I am trying to delete List item from Flat List .
Data is populating from JSON on Flat List now I have to delete particular list item data form list , for that I am using "Swipeout" . but getting error "Type error: undefined is not an object(evaluting this.2.viewNote.bind")
Please help . Where am going wrong and how can I do this
import React, { Component } from 'react';
import { View, Text, TextInput,
FooterTab,Button,TouchableOpacity, ScrollView, StyleSheet,
ActivityIndicator ,Header,FlatList} from 'react-native';
import {Icon} from 'native-base';
import { Table, Row, Rows } from 'react-native-table-component';
import { createStackNavigator } from 'react-navigation';
import { SearchBar } from 'react-native-elements';
import Swipeout from 'react-native-swipeout';
let swipeBtns = [{
text: 'Delete',
backgroundColor: 'red',
underlayColor: 'rgba(0, 0, 0, 1, 0.6)',
onPress: () => { this.deleteNote(item) }
}];
export default class OpenApplianceIssue extends Component {
constructor() {
super();
this.state = {
AbcSdata: null,
loading: true,
search: '',
tableData: [], qrData: '', selectedPriority: '',
selectedIssue: '', selectedReason: '', selectedTriedRestart: '',
selectedPowerLED: '', selectedBurning: '', selectedNoise: '',
};
this.setDate = this.setDate.bind(this);
}
setDate(newDate) {
}
_loadInitialState = async () => {
const { navigation } = this.props;
const qdata = navigation.getParam('data', 'NA').split(',');
var len = qdata.length;
const tData = [];
console.log(len);
for(let i=0; i<len; i++)
{
var data = qdata[i].split(':');
const entry = []
entry.push(`${data[0]}`);
entry.push(`${data[1]}`);
tData.push(entry);
}
this.setState({tableData: tData } );
console.log(this.state.tableData);
this.setState({loading: true});
}
componentDidMount() {
this._loadInitialState().done();
this.createViewGroup();
}
createViewGroup = async () => {
try {
const response = await fetch(
'http:/Dsenze/userapi/sensor/viewsensor',
{
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
"password": 'admin',
"username": 'admin',
"startlimit":"0",
"valuelimit":"10",
}),
}
);
const responseJson = await response.json();
const { sensorData } = responseJson;
this.setState({
AbcSdata: sensorData,
loading: false,
});
} catch (e) {
console.error(e);
}
};
updateSearch = search => {
this.setState({ search });
};
keyExtractor = ({ id }) => id.toString();
keyExtractor = ({ inventory }) => inventory.toString();
renderItem = ({ item }) => (
<Swipeout right={swipeBtns}>
<TouchableOpacity
style={styles.item}
activeOpacity={0.4}
onPress={this.viewNote.bind(this, item)} >
<Text >Id : {item.id}</Text>
<Text>Inventory : {item.inventory}</Text>
<Text>SensorType : {item.sensorType}</Text>
<Text>TypeName : {item.typeName}</Text>
</TouchableOpacity>
</Swipeout>
);
viewNote(item) {
this.props.navigator.push({
title: 'The Note',
component: ViewNote,
passProps: {
noteText: item,
noteId: this.noteId(item),
}
});
}
onClickListener = (viewId) => {
if(viewId == 'tag')
{
this.props.navigation.navigate('AddSensors');
}}
renderSeparator = () => {
return (
<View
style={{
height: 1,
width: "86%",
backgroundColor: "#CED0CE",
}}
/>
);
};
render() {
const { loading, AbcSdata } = this.state;
const state = this.state;
return (
<ScrollView>
<View style={styles.container1}>
<Button full rounded
style={{fontSize: 20, color: 'green'}}
styleDisabled={{color: 'red'}}
onPress={() => this.onClickListener('tag')}
title="Add Sensors"
>
Add Sensors
</Button>
</View>
<View style={styles.container1}>
{this.state.loading ? (
<ActivityIndicator size="large" />
) :
(
<FlatList
data={AbcSdata}
renderItem={this.renderItem}
keyExtractor={this.keyExtractor}
ItemSeparatorComponent={this.renderSeparator}
/>
)}
</View>
<View>
<Text
style={{alignSelf: 'center', fontWeight: 'bold', color: 'black'}} >
Inventory Details
</Text>
<Table borderStyle={{borderWidth: 2, borderColor: '#c8e1ff', padding:10,paddingBottom: 10}}>
<Rows data={state.tableData} textStyle={styles.text}/>
</Table>
</View>
</ScrollView>
);
}
}
const styles = StyleSheet.create(
{
container1:
{
flex: 1,
alignItems: 'stretch',
fontFamily: "vincHand",
color: 'blue'
},
header_footer_style:{
width: '100%',
height: 44,
backgroundColor: '#4169E1',
alignItems: 'center',
justifyContent: 'center',
color:'#ffffff',
},
Progressbar:{
justifyContent: 'center',
alignItems: 'center',
color: 'blue',
},
ListContainer :{
borderColor: '#48BBEC',
backgroundColor: '#000000',
color:'red',
alignSelf: 'stretch' ,
},
container2:
{
flex: 1,
justifyContent: 'center',
alignItems: 'stretch',
paddingHorizontal: 15
},
inputBox:{
width:300,
borderColor: '#48BBEC',
backgroundColor: '#F8F8FF',
borderRadius:25,
paddingHorizontal:16,
fontSize:16,
color:'#000000',
marginVertical:10,
},
button:{
width:300,
backgroundColor:'#4169E1',
borderRadius:25,
marginVertical:10,
paddingVertical:16
},
buttonText:{
fontSize:16,
fontWeight:'500',
color:'#ffffff',
textAlign:'center'
},
textStyle:{
fontSize:16,
fontWeight:'500',
color:'#ffffff',
textAlign:'center'
},
item:
{
padding: 15
},
text:
{
fontSize: 18
},
button:{
width:300,
backgroundColor:'#4169E1',
borderRadius:25,
marginVertical:10,
paddingVertical:16
},
buttonText:{
fontSize:16,
fontWeight:'500',
color:'red',
textAlign:'center'
},
separator:
{
height: 2,
backgroundColor: 'rgba(0,0,0,0.5)'
},
container: { flex: 1, padding: 16, paddingTop: 30, backgroundColor: '#fff' },
head: { height: 40, backgroundColor: '#f1f8ff' },
text: { margin: 6 }
});
Thanks .
First thing first,
Try using fat-arrow functions whenever possible, which will automatically solve your binding issues.
You will have to use the extraData= {this.state.activeRow} in your flatlist with newly added state activeRow.
I have updated your renderItem().
Check out the following updated code. Hope this helps.
import * as React from 'react';
import { View, Text, TextInput,
FooterTab, Button, TouchableOpacity, ScrollView, StyleSheet,
ActivityIndicator, Header, FlatList } from 'react-native';
import { Table, Row, Rows } from 'react-native-table-component';
import { createStackNavigator } from 'react-navigation';
import { SearchBar } from 'react-native-elements';
import { Constants } from 'expo';
// You can import from local files
import AssetExample from './components/AssetExample';
// or any pure javascript modules available in npm
import { Card } from 'react-native-paper';
import Swipeout from 'react-native-swipeout';
export default class App extends React.Component {
constructor() {
super();
this.state = {
AbcSdata: null,
loading: true,
search: '',
tableData: [], qrData: '', selectedPriority: '',
selectedIssue: '', selectedReason: '', selectedTriedRestart: '',
selectedPowerLED: '', selectedBurning: '', selectedNoise: '',
rowID:'',
activeRow: null
};
this.setDate = this.setDate.bind(this);
}
swipeBtns = [{
text: 'Delete',
type: 'delete',
backgroundColor: 'red',
underlayColor: 'rgba(0, 0, 0, 1, 0.6)',
onPress: () => {
console.log("Deleting Row with Id ", this.state.activeRow);
this.deleteNote(this.state.activeRow);
}
}];
removeItem = (items, i) =>
items.slice(0, i).concat(items.slice(i + 1, items.length));
deleteNote = (rowIndex) => {
//add your custome logic to delete the array element with index.
// this will temporary delete from the state.
let filteredData = this.removeItem(this.state.AbcSdata,rowIndex);
this.setState({AbcSdata: [] },()=> {
this.setState({AbcSdata: filteredData },()=> {console.log("Row deleted.", rowIndex)});
});
};
setDate(newDate) {
}
_loadInitialState = async () => {
const { navigation } = this.props;
const qdata = navigation.getParam('data', 'NA').split(',');
var len = qdata.length;
const tData = [];
console.log(len);
for (let i = 0; i < len; i++) {
var data = qdata[i].split(':');
const entry = []
entry.push(`${data[0]}`);
entry.push(`${data[1]}`);
tData.push(entry);
}
this.setState({ tableData: tData });
console.log(this.state.tableData);
this.setState({ loading: true });
}
componentDidMount() {
//this._loadInitialState().done();
this.createViewGroup();
}
createViewGroup = async () => {
try {
const response = await fetch(
'/Dsenze/userapi/sensor/viewsensor',
{
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
"password": 'admin',
"username": 'admin',
"startlimit": "0",
"valuelimit": "10",
}),
}
);
const responseJson = await response.json();
const { sensorData } = responseJson;
this.setState({
AbcSdata: sensorData,
loading: false,
});
} catch (e) {
console.error(e);
}
};
updateSearch = search => {
this.setState({ search });
};
keyExtractor = ({ id }) => id.toString();
keyExtractor = ({ inventory }) => inventory.toString();
onSwipeOpen(rowId, direction) {
if(typeof direction !== 'undefined'){
this.setState({activeRow:rowId});
console.log("Active Row",rowId);
}
}
renderItem = ({ item, index }) => (
<Swipeout
right={this.swipeBtns}
close={(this.state.activeRow !== index)}
rowID={index}
sectionId= {1}
autoClose = {true}
onOpen = {(secId, rowId, direction) => this.onSwipeOpen(rowId, direction)}
>
<TouchableOpacity
style={styles.item}
activeOpacity={0.4}
onPress={this.viewNote(item)} >
<Text >Id : {item.id}</Text>
<Text>Inventory : {item.inventory}</Text>
<Text>SensorType : {item.sensorType}</Text>
<Text>TypeName : {item.typeName}</Text>
</TouchableOpacity>
</Swipeout>
);
viewNote =(item) => {
this.props.navigator.push({
title: 'The Note',
component: this.ViewNote,
passProps: {
noteText: item,
noteId: this.noteId(item),
}
});
console.log("View Note Success");
}
onClickListener = (viewId) => {
if (viewId == 'tag') {
this.props.navigation.navigate('AddSensors');
}
}
renderSeparator = () => {
return (
<View
style={{
height: 1,
width: "86%",
backgroundColor: "#CED0CE",
}}
/>
);
};
render() {
const { loading, AbcSdata } = this.state;
const state = this.state;
return (
<ScrollView>
<View style={styles.container1}>
<Button full rounded
style={{ fontSize: 20, color: 'green' }}
styleDisabled={{ color: 'red' }}
onPress={() => this.onClickListener('tag')}
title="Add Sensors"
>
Add Sensors
</Button>
</View>
<View style={styles.container1}>
{this.state.loading ? (
<ActivityIndicator size="large" />
) :
(
<FlatList
data={AbcSdata}
renderItem={this.renderItem}
keyExtractor={this.keyExtractor}
extraData= {this.state.activeRow}
ItemSeparatorComponent={this.renderSeparator}
/>
)}
</View>
<View>
<Text
style={{ alignSelf: 'center', fontWeight: 'bold', color: 'black' }} >
Inventory Details
</Text>
<Table borderStyle={{ borderWidth: 2, borderColor: '#c8e1ff', padding: 10, paddingBottom: 10 }}>
<Rows data={state.tableData} textStyle={styles.text} />
</Table>
</View>
</ScrollView>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
padding: 8,
},
paragraph: {
margin: 24,
fontSize: 18,
fontWeight: 'bold',
textAlign: 'center',
},
});

Categories

Resources