React Native Flatlist nested loop - reactjs

I get this data as a response
[
{
"breakfast": [
"3x Eggs",
"2x Bread",
"Cup of Milk",
],
"lunch": [
"1/4 Chicken breast",
],
"dinner": [
"1x Apple",
],
"snack": [],
"_id": "5dd5224d76cf581424e1bb84",
},
]
I want to display them like this
here is my code
async componentDidMount(){
const breakfast = [];
const headers = {
'Authorization': GLOBAL.jwt
};
await axios({
method: 'GET',
url: 'http://192.168.1.101:4040/users/dietData',
headers: headers,
}).then((response) => {
response.data.forEach(item => {
breakfast.push(item.breakfast)
breakfast.forEach(item => { console.log(item)})
})
this.setState({
breakfast: breakfast,
dataSource: response.data,
});
}).catch((error) => {
Toast.show({
text: "[Error] Network Error, Please try again later",
buttonText: "Okay",
type: "danger",
duration: 3000
})
});
}
weightData = ({item}) => {
item.breakfast.forEach(
item => {
console.log(item)
return (
<ListItem>
<Text>{item}</Text>
<CheckBox style={{ marginLeft:210, alignSelf: 'flex-end'}} checked={false} color="#FC7B04" />
</ListItem>
)
}
);
}
render() {
return (
<View style={styles.dietCard}>
<FlatList
inverted
data={this.state.dataSource}
renderItem={ this.weightData }
keyExtractor={(item, index) => index}
/>
</View>
);
}
and here is the result of the console.log(item)
3x Eggs
2x Bread
Cup of Milk
but the problem is nothing is showing on the screen I tried to re-irritate the items so 3 items are shown but with no luck? any ideas?
and if I removed the foreach loop i get the 3 elements of the array in the same listitem not i want them in seperate list items

Use SectionList like below which full-fill your requirement.
<SectionList
sections={DATA}
keyExtractor={(item, index) => item + index}
renderItem={({ item }) => <Item title={item} />}
renderSectionHeader={({ section: { title } }) => (
// your renderUI view code is here..
)}
/>
follow below link for more details.
https://facebook.github.io/react-native/docs/sectionlist

Related

How to create automatic Item Divider for React Native FlatLists?

I have a list of events that I am rendering in a FlatList. I would like there to be a divider whenever the event is on a different date - aka when {item.eventID.eventDate} for a given item is different to the one before it (I already know how to call the sever to return the dates in order).
Is there a way to autogenerate these dividers?
Here is my function for each item of the FlatList:
function Item({ item }) {
return (
<View>
<Text>{item.eventID.eventDate}</Text>
<Text>{item.eventID.artistName}</Text>
<Text>{item.ticketID}</Text>
</View>
);
}
And here is my class component for the page:
export default class MyEventsScreen extends Component {
state = {
tickets: [],
};
componentDidMount = () => {
fetch("http://127.0.0.1:8000/api/fullticket/", {
method: "GET",
})
.then((response) => response.json())
.then((responseJson) => {
this.setState({
tickets: responseJson,
});
})
.catch((error) => {
console.error(error);
});
};
render() {
return (
<View>
<FlatList
style={{ flex: 1 }}
data={this.state.tickets}
renderItem={({ item }) => <Item item={item} />}
keyExtractor={(item) => item.ticketID}
/>
</View>
);
}
}
You can write a custom function to render divider when the date value is changed.
The new Item function and renderDivider:
let prevDate = ""
function renderDivider(date) {
if(prevDate === "" || date !== prevDate) {
prevDate = date //initialize prevDate
return <Text style={styles.divider}>----{date}---</Text>
}
}
function Item({ item }) {
return (
<View>
{renderDivider(item.eventID.eventDate)}
<Text>{item.eventID.artistName}</Text>
</View>
);
}
const styles = StyleSheet.create({
divider: {
marginVertical: 15,
fontWeight: '700',
color: 'rgb(100,100,100)'
}
});

RefrenceError: Can't find variable in react native

I tried to access all the files in a custom folder I created on my RNCamera roll app to create a gallery with it. In my code I believe i specified the variable "videos", but still am getting a reference error: "can't find variable videos", what do i do to solve it, how will i be able to get rid of the error.... here is my code...
I added constructor in the this.state but still get the same error
constructor() {
super();
this.state = {
modalVisible: false,
videos: [],
index: null
}
}
getPhotos = () => {
CameraRoll.getPhotos({
first: 20,
groupTypes: 'Album',
groupName: 'Custom VideoFolder',
assetType: 'Videos'
})
.then(r => this.setState({ videos: r.edges}))
.then((statResult) => {
let videos = []
var allowedExtensions = /(\.avi|\.mp4|\.mov|\.wmv|\.avi)$/i;
statResult.forEach(item => {
if (item.isFile() && !allowedExtensions.exec(item.originalFilepath)) {
videos.push(item)
}
});
console.log(videos)
})
}
toggleModal = () => {
this.setState({ modalVisible: !this.state.modalVisible})
}
share = () => {
const vocvideo = this.state.videos[this.state.index].node.video.uri
RNFetchBlob.fs.readFile(vocvideo, 'uri')
.then((data) => {
let shareOptions = {
title: "React Native Share Example",
message: "Check out this video!",
url: `data:video/mp4;uri,${data}`,
subject: "Check out this video!"
};
Share.open(shareOptions)
.then((res) => console.log('res:', res))
.catch(err => console.log('err', err))
})
}
render() {
console.log('state :', this.state)
return (
<View style={styles.container}>
<Button
title='View videos'
onPress={() => { this.toggleModal(); this.getPhotos() }}
/>
<Modal
animationType={"slide"}
transparent={false}
visible={this.state.modalVisible}
onRequestClose={() => console.log('closed')}
>
<View style={styles.modalContainer}>
<Button
title='Close'
onPress={this.toggleModal}
/>
<ScrollView
contentContainerStyle={styles.scrollView}>
{
this.state.videos.map((p, i) => {
const isSelected = i === this.state.index;
const divide = isSelected && this.share === true ? 1 : 3;
return (
<Video
style={{opacity: i === this.state.index ? 0.5 : 1, width: width/divide, height: width/divide}}
key={i}
underlayColor='transparent'
onPress={() => this.setIndex(i)}
source={{uri: video}}
/>
)
})
}
</ScrollView>

Material-Table with React: how to use star rating in the cell?

I would like to style my cell's rating into star by using Material-Table,
like the original Material-UI provided:
https://material-ui.com/components/rating/
Is it possible to use in Material-Table? I cannot find document related to this...just for the style for background, color, etc., not for writing functions in cell style.
https://material-table.com/#/docs/features/styling
thanks a lot!
You can use material-table's custom edit component to render the mui Rating component.
Full Working demo
Sample code snippet of columns array
const columns = propValue => [
{ title: "Id", field: "id" },
{ title: "First Name", field: "first_name" },
{
title: "Rating",
field: "rating",
render: rowData => {
return <Rating name="hover-feedback" value={rowData.rating} readOnly />;
},
editComponent: props => (
<Rating
name="hover-feedback"
value={props.value}
onChange={(event, newValue) => {
props.onChange(newValue);
}}
/>
),
cellStyle: {
backgroundColor: "#039be5",
color: "#FFF"
},
width: "30%"
}
];
Component
class App extends Component {
tableRef = React.createRef();
propValue = true;
state = { data: [] };
componentDidMount() {
const query = 0;
let url = "https://reqres.in/api/users?";
url += "per_page=" + query.pageSize;
url += "&page=" + (query.page + 1);
fetch(url)
.then(response => response.json())
.then(result => {
console.log("result", result);
this.setState({
data: result.data.map(d => ({ ...d }))
});
});
}
render() {
return (
<div style={{ maxWidth: "100%" }}>
<MaterialTable
icons={tableIcons}
tableRef={this.tableRef}
columns={columns(this.propValue)}
editable={{
onRowUpdate: (newData, oldData) =>
new Promise((resolve, reject) => {
console.log("newData", newData);
console.log("oldData", oldData);
const dataUpdate = [...this.state.data];
const index = oldData.tableData.id;
dataUpdate[index] = newData;
this.setState({ data: dataUpdate }, () => {
console.log("xx", this.state.data);
resolve(this.state);
});
})
}}
data={this.state.data}
title="Remote Data Example"
options={{ tableLayout: "fixed" }}
/>
<button
onClick={() => {
this.tableRef.current.onQueryChange();
}}
>
ok
</button>
</div>
);
}
}

fetch data from api in Accordion list react native

I want to fetch the title from
https://facebook.github.io/react-native/movies.json
in accordion view in react native
how can i do this
here is my code but is display static data using array
now i want to display data from api
const dataArray = [
{
title: "First Element",
content:""
},
{
title: "Second Element",
content:
"content1"
},
{
title: "Third Element",
content:
"content2"
}
];
class LocationScreen extends Component {
componentDidMount(){
return fetch('https://facebook.github.io/react-native/movies.json ')
.then((response) => response.json())
.then((responseJson) => {
this.setState({
isLoading: false,
dataSource: responseJson.data,
}, function(){
});
})
.catch((error) =>{
console.error(error);
});
}
render() {
return (
<Container>
<Content padder>
<Accordion
dataArray={dataArray}
/>
</Content>
</Container>
);
}
Replace {dataArray} by {this.state.dataSource}
render() {
return (
<Container>
<Content padder>
<Accordion
dataArray={this.state.dataSource}
/>
</Content>
</Container>
);
}
As suggest #slashsharp, use this.state.dataSource.
In the render method, you're using '{dataArray}' which is your static data.
If you want to start to display these static values, use this:
const dataArray = [
{
title: "First Element",
content:""
},
{
title: "Second Element",
content:
"content1"
},
{
title: "Third Element",
content:
"content2"
}
];
class LocationScreen extends Component {
state = {
dataSource: dataArray, //init state with your static data
}
componentDidMount(){
return fetch('https://facebook.github.io/react-native/movies.json ')
.then((response) => response.json())
.then((responseJson) => {
this.setState({
isLoading: false,
dataSource: responseJson.data,
}, function(){
});
})
.catch((error) =>{
console.error(error);
});
}
render() {
return (
<Container>
<Content padder>
<Accordion
dataArray={this.state.dataSource} // changed to this.state.dataSource
/>
</Content>
</Container>
);
}
Change the
this.setState({
dataSource:responseJson.movies
}
and use dataArray={this.state.dataSource}
renderContent(section, _, isActive) {
return (
<Animatable.View
duration={400}
style={[
style.wrapServiceDesc,
isActive ? style.seriveActiveDesc : style.seriveInactiveDesc
]}
transition="backgroundColor"
>
<Animatable.Text
animation={isActive ? "bounceIn" : undefined}
style={[style.serviceDesc]}
>
{section.text} // fetch from API
</Animatable.Text>
</Animatable.View>
);
}
componentDidMount() {
const url = "url";
fetch(url)
.then(response => response.json())
.then(responseJson => {
this.setState({
dataSource: responseJson.data
});
})
.catch(error => {
console.log(error);
});
}
render() {
return (
<Container>
<Content padder>
<Accordion
activeSections={activeSections}
sections={this.state.dataSource}
touchableComponent={TouchableOpacity}
expandMultiple={multipleSelect}
renderHeader={this.renderHeader}
renderContent={this.renderContent}
duration={400}
onChange={this.setSections}
/>
</Content>
</Container>
);
}
renderContent(section, _, isActive) {
return (
<Animatable.View
duration={400}
style={[
style.wrapServiceDesc,
isActive ? style.seriveActiveDesc : style.seriveInactiveDesc
]}
transition="backgroundColor"
>
<Animatable.Text
animation={isActive ? "bounceIn" : undefined}
style={[style.serviceDesc]}
>
{section.text} // fetch from API
</Animatable.Text>
</Animatable.View>
);
}
componentDidMount() {
const url = "url";
fetch(url)
.then(response => response.json())
.then(responseJson => {
this.setState({
dataSource: responseJson.data
});
})
.catch(error => {
console.log(error);
});
}
render() {
return (
<Container>
<Content padder>
<Accordion
activeSections={activeSections}
sections={this.state.dataSource}
touchableComponent={TouchableOpacity}
expandMultiple={multipleSelect}
renderHeader={this.renderHeader}
renderContent={this.renderContent}
duration={400}
onChange={this.setSections}
/>
</Content>
</Container>
);
}

Is it possible to assign a value (id) to animations in React Native?

Say if my animation is being iterated 20 times, but I don't want all of them playing at the same time. How would I go about triggering that one specific animation that have a value of 1. If I clicked on 1 then the other 19 should not trigger except that 1.
export default class AnimateScreen extends React.PureComponent {
constructor(props){
super(props);
this.forceUpdateHandler = this.forceUpdateHandler.bind(this);
this.state = {
dataSource: '',
progress: new Animated.Value(0),
};
animate = (id) => {
Animated.timing(this.state.progress, {
toValue: 1,
duration: 5000,
easing: Easing.linear,
}).start([id]); <!-- Here is my attempt in trying to animate that one specific animation.
render(){
return(
<FlatList
data={this.state.dataSource}
renderItem={({item}) =>
<View>
<View>
<Text>Work in progress</Text>
<View>
<TouchableHighlight
onPress={this.animate.bind(this, item.id)}>
<Animation
progress={this.state.progress}
source={require('../tools/animations/heart_icon.json')}
/>
</TouchableHighlight>
<Text> Hello</Text>
</View>
</View>
</View>
}
keyExtractor={(item, index) => index.toString()}
/>
);
}
}
I tried this out and still, all of the animations triggered. Is there a way to trigger them specifically?
DataSource:
"dataSource":[{"id":"10","images":"Emerson live in the sunshine swim in the sea drink the wild air.jpg","note":"Hello","tag":"sunshine"}
componentDidUpdate(prevProps, prevState) {
if (!prevState.dataSource) {
return fetch(`https://www.website.com/React/json-data.php` , {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
}
})
.then((response) => response.json())
.then((responseJson) => {
this.setState({
dataSource: responseJson,
},function() {
// In this block you can do something with new state.
});
})
.catch((error) => {
console.error(error);
});
}
}
Basically you can add progress key to each item in the dataSource with an animated value to 0 then on click you will animate that item's progress. It should roughly look like this:
export default class AnimateScreen extends React.PureComponent {
constructor(props){
super(props);
this.forceUpdateHandler = this.forceUpdateHandler.bind(this);
this.state = {
dataSource: [],
progress: new Animated.Value(0),
};
componentDidUpdate(prevProps, prevState) {
if (!prevState.dataSource) {
return fetch(`https://www.website.com/React/json-data.php` , {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
}
})
.then((response) => response.json())
.then((responseJson) => {
this.setState({
dataSource: responseJson.map(item => ({ ...item, progress: new Animated.Value(0) })), // Add progress key
},function() {
// In this block you can do something with new state.
});
})
.catch((error) => {
console.error(error);
});
}
}
animate = (item) => {
Animated.timing(item.progress, {
toValue: 1,
duration: 5000,
easing: Easing.linear,
}).start(); <!-- Here is my attempt in trying to animate that one specific animation.
render(){
return(
<FlatList
data={this.state.dataSource}
renderItem={({item}) =>
<View>
<View>
<Text>Work in progress</Text>
<View>
<TouchableHighlight
onPress={() => this.animate(item)}>
<Animation
progress={item.progress}
source={require('../tools/animations/heart_icon.json')}
/>
</TouchableHighlight>
<Text> Hello</Text>
</View>
</View>
</View>
}
keyExtractor={(item, index) => index.toString()}
/>
);
}
}

Resources