Separate sectionlist data in react native - 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,
},
});

Related

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.

Why response type is different?

I am building a simple gallery management app with React Native.
In gallery page, I called "FetchGallery" function and in there, I got some response.
This is constructor part.
this.state = {
mainGalleryData: [
{
bg_url: '',
country_id: 0
}
],
};
That is the code for response.
_onFetchGalleryBySite = (e) => {
fetch(config.api.getGalleryInfo + '/' + e, {
method: 'GET',
headers: this.state.myHeaders
})
.then((response) => response.json())
.then((responseJSON) => {
console.log('resJSON=>', responseJSON['gallery_list']); // => log is in the below.
responseJSON['gallery_list'].map(item => {
if (item != "") {
let obj = {}
obj.bg_url = item.bg_url
obj.country_id = item.country_id
this.state.mainGalleryData.push(obj)
}
})
})
.catch(err => console.log('_onFetchGalleryInfoErr=>', err))
}
This is the log of fetched data
resJSON => [{ "bg_url": "staff_upload/bgremoval_20201008030228.png", "country_id": "3" },
{ "bg_url":"Guest/1/image/bgremoval_20201004222851.png", "country_id": "3" }]
And in the render() , I used this data in the flatList
That is the code for FlatList
<FlatList
data={mainGalleryData}
renderItem={this.renderGallery}
keyExtractor={(item, index) => index.toString()}
/>
This is the renderGallery.
renderGallery = (item) => (
<TouchableOpacity onPress={() => console.log('itemClicked=>', item)} style={styles.overlay}>
<Image source={newImg} style={styles.newImg} />
{
this.state.gallery_id == item.location_id ?
<Text style={{ fontWeight: '700' }} numberOfLines={1}>{item.item.title}</Text>
:
<Text style={{ fontSize: 12 }} numberOfLines={1}>{item.item.title}</Text>
}
</TouchableOpacity>
)
When I click one of those data, I want to get this data. But the result is different that I expect.
I want: { "bg_url": "staff_upload/bgremoval_20201008030228.png", "country_id": "3" }
result: { "index": 2, "item": {"Guest/1/image/bgremoval_20201004222851.png", "country_id": "3"}}
So I had to get country_id with "item.item.country_id".
I want to get country_id with "item.country_id".
What is this <"index": 2> ?
Before pushing response in state, please clear "mainGalleryData[]"
because default it has 1 item in state which makes index
inappropriate.
Do this
console.log('resJSON=>', responseJSON['gallery_list']);
const responseData = responseJSON['gallery_list'];
const data = this.state.mainGalleryData.concat(responseData); <-- add this line -->
this.state({ mainGalleryData: data });

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>
))}
)
}

Same screen with different Nested Json array data in React-native

I am trying to display same screen with different parameter in react-native. i checked with https://snack.expo.io/#react-navigation/navigate-with-params-v3. its working fine. But i have to display the different data in same screen. My expectation is in tree view structure data have to display like in our normal system tile view folder structure.
Expected Output view:
The view like normal our system folder title structure. C:/user/ReactNative/file .. like tile view.
Ex:
1.FamilyScreen.js
params : Gradpa -> while click Grandpa it will navigate to same page but the data change as 'Father'
FamilyScreen.js
params:Me - While click 'Father' it will navigate to same page but the data as 'Erick and Rose'.
The data will come from service so it may contain some more than children. it will variant. How to pass the particular data in react-native.
const family = [
{
id: 'Grandparent',
name: 'Grandpa',
age: 78,
children: [
{
id: 'Father',
name: 'Father',
age: 30,
children: [
{
id: 'Erick',
name: 'Erick',
age: 10,
},
{
id: 'Rose',
name: 'Rose',
age: 12,
},
],
},
],
},
]
Thanks
Finaly its working, here my code is
constructor(props) {
super(props)
this.state = {
res:family,
}
this.getNestedData = this.getNestedData.bind(this);
}
getNestedData (item) {
var data;
Object.keys(item).map((propKey) => {
if ( propKey === 'children'){
data=item[propKey]
}
})
this.props.navigation.push('GridScreen',{
data:data
});
}
Item = ({ item }) => {
return (
<View style={styles.item}>
<Text style={styles.title} onPress={this.getNestedData.bind(this,item)}>{item.name}</Text>
</View>
);
}
render() {
const { navigation } = this.props;
const data = navigation.getParam('data', this.state.res);
return (
<View>
<FlatList
data={data }
renderItem={({ item }) => <this.Item item={item} />}
keyExtractor={item => item.id}
numColumns={3}
/>
</View>
)
}
}

Accessing ref with the onFocus callback while using tcomb-form-native

I'm using https://github.com/gcanti/tcomb-form-native
& here's the snippet of code
_renderScene(route, navigator) {
var Cook_time = {
onFocus: () => {
console.log('cook time has focus');
console.log(this.refs);
},
};
options.fields['Cook_time'] = Cook_time;
return (
<View style={{ flex: 1 }}>
<ScrollView style={styles.container} ref="scrollView">
<Form
ref="form"
type={Recipe}
options={options}
onChange={this.onChange}
onFocus={this.onChange}
/>
console.log prints object{} when it should refer to scrollView, not sure what I might be missing. And here's the code that sets up the form itself
var Recipe = t.struct({
Recipe_name: t.String,
yield: t.maybe(t.String),
Prep_time: t.maybe(t.String),
Cook_time: t.maybe(t.String),
source: t.maybe(t.String),
})
var options = {
fields: {
yield: {
label: 'Yield',
},
Prep_time: {
label: 'Preparation time',
},
source: {
label: 'Source',
placeholder: 'family, friends, website ...',
onFocus: function () {
console.log('source has focus');
}
}
}
};
ref attribute is a callback and as per react-native documentation
all I need to do is save a reference as so
<ScrollView style={styles.container} ref={(ref) => this.myScrollView = ref}>