How to render data that get from realm.objects - react-native

I'm using realm database for my react native applciation. I can able to create data into the realm database
const createANewCategory = ( categoryName ) => {
Realm.open( {
path: 'myrealm.realm',
schema: [CategorySchema],
} ).then( ( realm ) => {
realm.write( () => {
const result = realm.create( 'Category', {
id: Math.random().toString( 36 ).substring( 7 ),
category_name: categoryName
} );
console.log( "New category created", result );
} );
} );
setshowModal( false );
};
Fetched the data from realm database to render in flatlist
const [categories, setcategories] = useState( [] );
useEffect( () => {
Realm.open( {
path: 'myrealm.realm',
schema: [CategorySchema],
} ).then( ( realm ) => {
const categories = realm.objects( 'Category' );
getArrayFromObject( categories );
setcategories( categories );
} );
}, [] );
When I rendered data in flatlist, no data was rendered
<FlatList
data={ categories }
keyExtractor={ ( item ) => item.id }
renderItem={ itemData =>
<CategoryCard
onPress={ navigateToAllDocuments }
title={ itemData.item }
/>
}
/>
So the categories type returns object but it is array. That's why the categories not rendering in flatlist. Is there anyway to render data in flatlist

Related

React-admin SelectInput occurs out of range warning

I have SelectInput inside of ReferenceInput
As you can see below,
This is workaround version of code. the selection shows right data and it parses as I expected, however, a out-of-range value **[object Object]** is show. (please see the reference image below)
This is a code snippet of SelectInput component
const AddressSelectInput: FC<AddressSelectInputProps> = (
{
customerId,
source,
...props
}
) => {
const classes = useStyles()
const [choices, setChoices] = useState<InputSourceProps[] | undefined>()
// sorting data from props
useEffect(() => {
if (props.choices) {
const result: InputSourceProps[] | undefined = props.choices?.find(
item => item._id === customerId
)?.addresses?.map((item: UserAddress) => {
let res: InputSourceProps;
res = {
name: item.label,
description: item.place.description,
postalCode: item.place.postalCode,
location: {
lat: item.place.location.lat,
lng: item.place.location.lng
}
}
return res;
})
setChoices(result)
}
}, [props.choices, customerId])
if (!choices) {
return null
}
const optionRenderer = (choice: Place) => `${choice.name} - ${choice.description}`;
return (
<SelectInput
className={classes.selectInputStyle}
label="Addresses suggestion"
choices={choices}
source={source}
optionText={optionRenderer}
optionValue={'name'}
defaultValue=''
parse={(name: string) => choices.find(c => c.name === name)}
/>
)
}
this is parent component of SelectInput:
const RideReferenceAddressInput: FC<RideReferenceInputProps> = ({
source,
label,
customerId,
}) => {
const filterToQuery = (customerId: string) => (filter: string) => ({
$search: filter,
_id: customerId
})
return (
<ReferenceInput
reference="users"
source={source}
filterToQuery={filterToQuery(customerId)}
>
<AddressSelectInput source={source} label={label} customerId={customerId} />
</ReferenceInput>
)
}
Could anyone can help to remove the warning? and why this is warning shows?
Thank you all in advance!

react native: Rendering an array of strings and numbers doesn't work

In the react native app I'm retrieving some data from my backend and then want to display it to the app user:
when I log the data I can see that I receive it and stored it properly in the state as an object:
// console.log("received the data: ", this.state.data) ->
received the data: Object {
"a": 48,
"b": "2021-03-29T17:11:51Z",
"c": "",
"d": false
}
But when I try to render that in my view, the screen simply stays empty (no error message):
render() {
// let me check, if the data is really there
Object.entries(this.state.data).map(([key, value]) => {
console.log("key: ", key, "- value: ", value)
})
// output:
// key: a - value: 48,
// key: b - value: 2021-03-29T17:11:51Z,
// key: c - value: ,
// key:d - value: false
return (
<View>
{Object.entries(this.state.data).map(([key, value]) => {
return <View key={key}><Text>{value}</Text></View>
})}
</View>
)
}
I also tried this, but still I receive an empty screen:
render() {
return (
{ this.state.data.map((items, index) => {
return (
<ul key={index}>
{Object.keys(items).map((key) => {
return (
<li key={key + index}>{key}:{items[key]}</li>
)
})}
</ul>
)
})}
)
}
Edit: The full component:
import React from 'react'
import { View, Text } from 'react-native'
import axios from 'axios';
class SuccessScreen extends React.Component {
baseURL = "https://my-backend-server-URL.com/data"
state = {
data: {},
}
componentDidMount() {
this.startGetData();
}
startGetData = () => {
axios.get(this.baseUrl)
.then(response => {
console.log("got the data: ", response.data)
this.state.data = response.data;
})
.catch(function (err) {
//handle error
console.log("error getting data: ", err.message)
return {
type: "REGISTER_USER_FAILED",
payload: null
}
});
};
render() {
console.log("This log will show up")
return (
<View>
{this.state.vehicleData && Object.entries(this.state.vehicleData).map(([key, value]) => {
console.log("this log never shows up... key: ", key) // these logs don't not show up
return <View key={key}><Text>{value}</Text></View>
})}
</View>
)
}
}
export default SuccessScreen;
Wait for data to be defined, Try this:
return (
<View>
{this.state.data && Object.entries(this.state.data).map(([key, value]) => {
return <View key={key}><Text>{value}</Text></View>
})}
</View>
Edit:
Don't mutate this.state.data = response.data that way, use the setState:
this.setState({ data: response.data });
https://reactjs.org/docs/faq-state.html#what-does-setstate-do

remove duplicate error from JSON value React Native

I am trying to pass filtered value from JSON to the parent component, however I've tried using Set but seems the output is still the same. The component that I'm using to render the JSON is picker from native-base. I want to filter out the repeated value in my picker. Greatly appreciated if anyone can help me.
enter image description here
Here's my code.
Picker.js
const DefaultPicker = ({labelItem, pickerWidth, onHandleValue, ...rest}) => {
const context = useContext(WindowContext);
const [selectedValue, setSelectedValue] = useState('-Select-');
const [data, setData] = useState([]);
const {user, setUser} = useContext(AuthContext);
function onNewData() {
if (user) {
user.getIdToken().then((idToken) => {
Axios.get('URL_ENDPOINT', {
headers: {
Authorization: 'Bearer' + idToken,
},
})
.then(({data}) => {
setData(data.features);
// console.log(data.features);
})
.catch((error) => {
console.error(error);
});
});
}
}
useEffect(() => {
const form = onNewData(onNewData);
return form;
}, []);
return (
<PickerWrapper>
<PickerItem
width={pickerWidth}
height="60"
mode="dropdown"
selectedValue={selectedValue}
onValueChange={(itemValue, itemIndex) => {
setSelectedValue({itemValue});
}}>
{Array.from(
new Set(
data.map((value, index) => (
<PickerItem.Item
key={index}
label={value.properties[labelItem]}
value={value.properties[labelItem]}
{...rest}
/>
)),
),
)}
</PickerItem>
</PickerWrapper>
);
};
And here is my parent component
SiteData.js
const SiteData = () => {
const [values, setValues] = useState([]);
const onHandleValue = (params) => {
setValues(params);
console.log(params);
};
return (
<ScrollableView>
<DetailContainer>
<DetailWrapper>
<DetailTitle>Site Data</DetailTitle>
<DetailSubtitle marginTop="10">
Insert new data found during your audit or observation session
</DetailSubtitle>
<DetailSubcontainer>
<DefaultPicker
labelItem={'category'} <-- receive value from child
pickerWidth="100%"
onHandleValue={onHandleValue}
/>
</DetailSubcontainer>
</DetailWrapper>
</DetailContainer>
</ScrollableView>
);
};
UPDATE 1:
I'm using the filter() method so i can create a new array but it returns only one value in the picker list.
const indexData = data.filter(
({category}, index) => {
return (
data.findIndex(
(item) =>
item.category === category,
) === index
);
},
);
The output
enter image description here
I fixed my code by adding this on child component
var setObj = new Set();
var result = data.reduce((acc,item)=>{
if(!setObj.has(item.category)){
setObj.add(item.category,item)
acc.push(item)
}
return acc;
},[]);

Apollo-Client refetch - TypeError: undefined is not an object

I have a flatlist in react-native and I am trying to refetch the data when pulling it down (the native refresh functionality). When I do, I am getting this error:
Typeerror: undefined is not an object
I can't figure out what is going wrong. I am using
Expo SDK 38
"#apollo/client": "^3.1.3",
"graphql": "^15.3.0",
This is my code:
export default function DiscoverFeed({ navigation }) {
const theme = useTheme();
const { data, error, loading, refetch, fetchMore, networkStatus } = useQuery(
GET_RECIPE_FEED,
{
variables: { offset: 0 },
notifyOnNetworkStatusChange: true,
}
);
if (error) return <Text>There was an error, try and reload.</Text>;
if (loading) return <Loader />;
if (networkStatus === NetworkStatus.refetch) return <Loader />;
const renderItem = ({ item }) => {
return (
<View style={styles.cardItems}>
<RecipeCard item={item} navigation={navigation} />
</View>
);
};
return (
<SafeAreaView style={styles.safeContainer} edges={["right", "left"]}>
<FlatList
style={styles.flatContainer}
data={data.recipe}
removeClippedSubviews={true}
renderItem={renderItem}
refreshing={loading}
onRefresh={() => {
refetch();
}}
keyExtractor={(item) => item.id.toString()}
onEndReachedThreshold={0.5}
onEndReached={() => {
// The fetchMore method is used to load new data and add it
// to the original query we used to populate the list
fetchMore({
variables: {
offset: data.recipe.length,
},
});
}}
/>
</SafeAreaView>
);
}
I have a typepolicy like so:
export const cache = new InMemoryCache({
typePolicies: {
Query: {
fields: {
recipe: {
merge: (existing = [], incoming, { args }) => {
// On initial load or when adding a recipe, offset is 0 and only take the incoming data to avoid duplication
if (args.offset == 0) {
console.log("offset 0 incoming", incoming);
return [...incoming];
}
console.log("existing", existing);
console.log("incoming", incoming);
// This is only for pagination
return [...existing, ...incoming];
},
},
},
},
},
});
And this is the query fetching the data:
export const GET_RECIPE_FEED = gql`
query GetRecipeFeed($offset: Int) {
recipe(order_by: { updated_at: desc }, limit: 5, offset: $offset)
#connection(key: "recipe") {
id
title
description
images_json
updated_at
dishtype
difficulty
duration
recipe_tags {
tag {
tag
}
}
}
}
`;

Update position of All places in react-native-sortable-listview

I am using react-native-sortable-listview in react-native for sorting same places.
constructor() {
this.state = {
makers: [
{ kolkata: 'Hawrah Birdge' },
{ Delhi: 'Lal Kila' },
{ Agra: 'Taj Mahal' },
{ Mumbai: 'India Gate' },
],
allObj: {},
order: []
};
}
componentDidMount() {
const newAllObj = this.getAllObjFromMaker(this.state.makers);
const newOrder = this.getOrderFromMaker(newAllObj);
this.setState({ allObj: newAllObj, order: newOrder });
}
getAllObjFromMaker(makers) {
const allObj = makers.reduce((result, d) => {
result[`${d.coordinate.latitude}_${d.coordinate.longitude}`] = d;
return result;
}, {});
return allObj;
}
getOrderFromMaker(allObj) {
const order = Object.keys(allObj);
return order;
}
renderOneDraggableMilestone(milestone) {
const i = this.state.makers.indexOf(milestone);
return (
<TouchableOpacity {...this.props.sortHandlers}>
<Text>{i + 1}</Text>
<Text>{milestone.address}</Text>
</TouchableOpacity>
);
}
arrangedMilestoneList(e) {
const arr = this.state.makers;
arr.splice(e.to, 0, arr.splice(e.from, 1)[0]);
const newAllObj = this.getAllObjFromMaker(arr);
const newOrder = this.getOrderFromMaker(newAllObj);
this.setState({ makers: arr, allObj: newAllObj, order: newOrder
});
}
render() {
return (
<SortableListView
data={this.state.allObj}
order={this.state.order}
activeOpacity={0.5}
onRowMoved={e => {
this.arrangedMilestoneList(e);
this.forceUpdate();
}}
renderRow={(row) => this.renderOneDraggableMilestone(row)}
/>
);
}
I want to arrange places and also their position in this.state.makers as I am doing using i in renderOneDraggableMilestone. On renderRow only draggable place are render so only their position is updated. And renderRow is last to excute so forceUpdate is also not working.
How to rerender after executing renderRow. So all position could be updated.
Ok I have find a way to re-render as follow.
<SortableListView
key={this.state.count}
data={this.state.allObj}
order={this.state.order}
activeOpacity={0.5}
onRowMoved={e => {
this.setState({ count: this.state.count + 1 });
this.props.arrangedMilestoneList(e);
console.log('onRowMoved is called');
}}
onMoveEnd={() => console.log('onMoveEnd is fired')}
renderRow={(row, s1, i) => this.renderOneDraggableMilestone(row, s1, i)}
/>
What I am doing is I added a key attribute to SortableListView and update this key on each onRowMoved action. And because of this it causes re-render.