How to display the nested array data in react native from API? - react-native

I am trying to fetch and display the data from API. Below response i am getting from the API. I want to show the value of "Name" from details array. Kindly help me to resolve this. i have tried below code
{
"Success":1,
"data":[
{
"Date":"2019-11-08",
"Details":[
{
"Name":"Name 1",
"Id":72
},
{
"Name":"Name 2",
"Id":73
}
]
},
{
"Date":"2019-11-09",
"Details":[
{
"Name":"Name 3",
"Id":72
},
{
"Name":"Name 4",
"Id":73
}
]
}
]
}

Javascript map function can be used for nested iteration.
Consider your data is stored in state as data.
If response is received in a variable named response you can set state as
this.setState({ data : response.data })
Then you can use the below code snippet to iterate through nested object values
{
this.state.data.map((dat, index) => { //Iterate through your data
return (
<View style={styles.selectedCh} key={"outer-" + index}>
<Text>{dat.Date}</Text>
{
dat.Details.map((inner, indexInner) => { //Iterate through inner Details
return (
<View style={{ flex: 1 }} key={"inner-" + indexInner} >
<Text>{inner.Id}</Text>
<Text>{inner.Name}</Text>
</View>
)
})
}
</View>
)
})
}

Related

How to pass data which is not relevant to render through Flatlist?

I create Flatlist as below.
export default function Comments({ route }) {
const renderComment = ({ item: comments }) => {
return <CommentRow {...comments} />;
};
return (
<Container>
<CommentBox>
<FlatList
keyboardDismissMode={true}
showsVerticalScrollIndicator={false}
data={route.params.comments}
keyExtractor={(comment) => "" + comment.id}
renderItem={renderComment}
/>
</CommentBox>
</Container>
);
}
rendered data set seems like below:
Object {
"key": "Comments-uxnCZKk0KvTmpppxkM8IF",
"name": "Comments",
"params": Object {
"comments": Array [
Object {
"__typename": "Comment",
"createdAt": "1642680008811",
"id": 1,
"isMine": false,
"payload": "등산 너무 좋았겠네~~",
"user": Object {
"__typename": "User",
"avatar": "https://chungchunonuploads.s3.ap-northeast-2.amazonaws.com/avatars/4-1642681358399-%E1%84%80%E1%85%B5%E1%86%B7%E1%84%8C%E1%85%A5%E1%86%BC%E1%84%92%E1%85%A9.png",
"username": "김정호",
},
},
Object {
"__typename": "Comment",
"createdAt": "1642680037676",
"id": 3,
"isMine": false,
"payload": "다음주에 그 산으로 가자 우리도~~",
"user": Object {
"__typename": "User",
"avatar": "https://chungchunonuploads.s3.ap-northeast-2.amazonaws.com/avatars/4-1642681358399-%E1%84%80%E1%85%B5%E1%86%B7%E1%84%8C%E1%85%A5%E1%86%BC%E1%84%92%E1%85%A9.png",
"username": "김정호",
},
},
],
"photoId": 1,
},
"path": undefined,
}
So It successfully works.
I return it to <CommentRow> Screen with this data set.
But I need to pass another data which is photoId.
this photoId exists in this screen but not in CommentRow Screen.
And comments data set doesn't have this photoId information. So I need separately send it to CommentRow Screen with {...comments} data.
But How can I send it through Flatlist?
I tried to make another object as combining comments object with photoId. But It failed :(
or Should I just bring photoId information in CommentRow screen as not passing through Flatlist?
If you need more explanation about my code, I can answer on real time.
please help me.
CommentRow Screen.
PhotoId is used in cache.modify part since it is needed to update my cache.
export default function CommentRow({
id,
user,
payload,
isMine,
createdAt,
updatedAt,
commentNumber,
}) {
const navigation = useNavigation();
const createdDate = new Date(+createdAt);
const date = createdDate.toISOString().substring(0, 10);
const updateDeleteComment = (cache, result) => {
const {
data: {
deleteComment: { ok, error },
},
} = result;
if (ok) {
cache.evict({ id: `Comment:${id}` });
cache.modify({
id: `Photo:${photoId}`,
fields: {
comments(prev) {
return [...prev, newCacheComment];
},
comments(prev) {
return prev +1;
}
}
})
}
};
const [deleteCommentMutation] = useMutation(DELETE_COMMENT_MUTATION, {
variables: {
id,
},
update: updateDeleteComment,
});
const onDeleteClick = () => {
deleteCommentMutation();
};
return (
<Container>
<CommentContainer>
<UserImage source={{ uri: user.avatar }} />
<TextBox>
<Header>
<Username>{user.username}</Username>
<CreatedTime>{date}</CreatedTime>
</Header>
<CommentText>{payload}</CommentText>
</TextBox>
</CommentContainer>
{isMine ? (
<WriteContainer>
<TouchableOpacity>
<WriteComment>수정</WriteComment>
</TouchableOpacity>
<TouchableOpacity onPress={onDeleteClick}>
<WriteComment>삭제</WriteComment>
</TouchableOpacity>
</WriteContainer>
) : null}
</Container>
);
}
Change renderComment as
const renderComment = ({ item: comments }) => {
const photoIdobj = { photoId: `${route.params.photoId}` };
const passedComments = { ...comments, ...photoIdobj };
return <CommentRow {...passedComments} />;
};
and call photoId from CommentRow like
export default function CommentRow({
id,
user,
payload,
isMine,
createdAt,
updatedAt,
commentNumber,
photoId
})
I got an idea from #Thanhal's answer.
I made the new object as combining comments and photoId as below.
then it works.
const renderComment = ({ item: comments }) => {
const photoIdobj = { photoId: `${route.params.photoId}` };
const passedComments = { ...comments, ...photoIdobj };
return <CommentRow {...passedComments} />;
};
return (

React Native Handle Nested Object with Map and Display

how to handle nested object with map for display on flatlist or text or other component at react native. i tried to display using text and flatlist but didnt work, i want to display like this
this is my code,
const Schedule = () => {
const [resp, setData] = useState([]);
useEffect(() => {
const fetchData = async () => {
const respData1 = await axios(
`http://sh3ll.my.id/api/data3.json`
);
setData({ data: respData1.data.data });
};
fetchData();
},[]);
console.log('render');
if (resp.data) {
console.log("d==>", resp);
}
return (
<View style={{paddingTop:20}}>
{ resp.data && resp.data.map((items,i)=>
<Text key={i}>{`${items.date} ${items.time}`}
{items.list.map((sub)=>{ `${sub.description}`
})}
</Text>
) }
{/* <FlatList data={resp}
keyExtractor={(x,i)=>i}
renderItem={({item})=>
....?? }
/> */}
</View>
)
}
export default Schedule
Looking at your code, I assume your data object looks like this:
const resp = {
data: [
{
date: "date 1",
time: "time 1",
list: [{ description: "desc 1" }, { description: "desc 2" }]
},
{
date: "date 2",
time: "time 2",
list: [{ description: "desc 1" }, { description: "desc 2" }]
}
]
};
If that's correct, you can flatten your object by calling your own "createDescription" function that will take care of rendering the descriptions:
function createDescription(listItem) {
return <p>{listItem.description}</p>;
}
return (
<table style={{ paddingTop: 20 }}>
{resp.data &&
resp.data.map((items, i) => (
<tr key={i}>
<td>{items.date}</td>
<td>{items.time}</td>
<td>{items.list.map((sub) => createDescription(sub))}</td>
</tr>
))}
</table>
);
Now that you have your HTML correctly rendered, you can fix the layout using CSS.

React navigation 5.0 undefined params

Passing data from one screen to another screen
<TouchableOpacity
onPress={() =>
this.props.navigation.navigate("CourseListBySubject", {
cateoryId: subject.id,
})
}
>
Tried to get param
render() {
//const { categoryId } = this.props.route.params;
console.log(this.props.route);
return <Text>Test</Text>;
}
Param is undefined in console output
Object {
"key": "CourseListBySubject-l0ynFMFcdC5uToYiupsGr",
"name": "CourseListBySubject",
"params": undefined,
}
Can anyone help to get param data in second screen?

React-Native Conditional Rendering with JSON data

I have data that looks like this:
// items.json
[
{
"key": 1,
"category": "Fruits",
"colors": [
{
"color": "red",
"favourite": "apple"
},
{
"color": "orange",
"favourite": "orange"
}
]
},
{
"key": 2,
"category": "Vegetables",
"colors": [
{
"color": "orange",
"favourite": "carrot"
},
{
"color": "green",
"favourite": "celery"
}
]
}
]
But it can have an unlimited amount of objects in each array. What I want to do is initially display the categories, which I have done like this:
import Items from './items.json';
// and then I use it in the render method
render() {
var items= items;
return (
{items.map(item =>
<TouchableOpacity
key={item.key}>
<Text>
{item.category}
</Text>
</TouchableOpacity>
)}
)
}
Now when a category is pressed I want to hide the categories and display the colors. And then when the color is pressed I want to hide the colors and display the favourite.
I have tried doing this with if else statements, but it that won't work if the data is replaced, and as I mentioned this json object can be quite large. Please help!
Declare two arrays in your state, one for storing the original data and one for storing the filtered data based on which item was pressed.
state = {
items: items, // original data
data: items, // will filter data and display using .map()
categoryIndex: 0, // index of the selected category
};
Add onPress to your TouchableOpacity and pass the type of the item that was pressed.
{this.state.data.map((item, index) => (
<TouchableOpacity
onPress={() =>
this.onItemPress(
item.category ? 'category' : item.color ? 'color' : 'favourite',
index
)
}
key={item.key}>
<Text>{item.category || item.color || item.favourite}</Text>
</TouchableOpacity>
))}
onItemPress, based on item that was pressed update state.data
onItemPress = (type, index) => {
if (type === 'category') {
this.setState({
data: this.state.items[index].colors,
categoryIndex: index,
});
}
if (type === 'color') {
this.setState({
data: [
{
favourite: this.state.items[this.state.categoryIndex].colors[index]
.favourite,
},
],
});
}
if (type === 'favourite') {
this.setState({
data: this.state.items,
categoryIndex: 0,
});
}
};
DEMO
You need to:
track in your component state what the selected item or color index is so your render function knows when to rerender and what to render.
handle when an item is pressed by adding the onPress prop to your TouchableOpacity and updating the component state as mentioned above
state = {
selectedItemIndex: null,
selectedColorIndex: null,
};
render {
if (this.state.selectedColorIndex) {
// return some jsx using this data below:
// items[this.state.selectedItemIndex].colors[this.state.selectedColorIndex].favourite
}
if (this.state.selectedItemIndex) {
return (
{items[this.state.selectedItemIndex].colors.map(color, i) => (
{/* return jsx here for colors */}
)}
);
}
return (
{items.map((item, i) => (
<TouchableOpacity
key={item.key}
onPress={() => this.setState({ selectedItemIndex: i })}>
<Text>
{item.category}
</Text>
</TouchableOpacity>
))}
)
}

Separate sectionlist data in react native

How can I separate the data to make my section list look like how it is in the picture?
https://i.stack.imgur.com/oABMf.png
It depends on the data structure you have. Lets assume you have this kind of data structure:
const data = [
{
id: 1,
text: "Fooo text 1",
description: "Foooo description 1"
},
{
id: 2,
text: "Fooo text 2",
description: "Foooo description 2"
},
]
function ListScreen() {
const sections = []
sections.push({ title: 'Title', data: data });
return (
<SectionList
sections={sections}
renderItem={({ item, index }) => <Text>{item.id}</Text>}
renderSectionHeader={SectionHeader}
keyExtractor={(item, index) => item.id.toString()}
/>
);
}
function SectionHeader({ section: { title } }) {
return (
<View style={styles.sectionHeader}>
<Text>{title}</Text>
</View>
);
}
const styles = StyleSheet.create({
sectionHeader: {
padding: 12,
},
});