Related
Code:
import React, { Component,useState } from 'react';
import {
StyleSheet,
View,
TouchableHighlight,
Text,
ToastAndroid,
ScrollView,
Modal,Button
} from 'react-native';
import ProgressCircle from 'react-native-progress-circle'
import AutoTags from 'react-native-tag-autocomplete';
import firebase from '../config';
import { TabView, SceneMap } from 'react-native-tab-view';
const db= firebase.database();
let itemsRef = db.ref('/dataset');
let input = db.ref('/tags');
let disease=[];
itemsRef.limitToFirst(10).on('value', (snapshot) => {
snapshot.forEach((childSnapshot) => {
disease.push(childSnapshot.val().Disease);
});
});
let addItem = item => {
input.push({
userSymptom: item
});
};
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {
tagsSelected:[],
storedTags:[],
index: 0,
routes: [
{ key: 'first', title: 'First' },
{ key: 'second', title: 'Second' },
{ key: 'third', title: 'Third'}],
modalVisible: false,
};
}
componentDidMount(){
let storedTags=[];
itemsRef.on('value', (snapshot) => {
snapshot.forEach((childSnapshot) => {
storedTags.push({'name':childSnapshot.val().Symptom});
});
});
let userSymptoms=[];
input.limitToLast(1).on('value', (snapshot)=>{
snapshot.forEach((childSnapshot)=>{
childSnapshot.val().userSymptom.forEach(element=>{
userSymptoms.push(element)
})
})
})
this.setState({ tagsSelected:userSymptoms})
this.setState({ storedTags: storedTags})
}
setModalVisible(visible){
this.setState({ modalVisible: visible });
}
Modal=()=>(
<View style={styles.centeredView}>
<Modal
animationType="slide"
transparent={true}
visible={this.state.modalVisible}
onRequestClose={() => {
console.log("Modal has been closed.");
}}
>
<View style={styles.centeredView}>
<View style={styles.modalView}>
<Text style={styles.modalText}>Hello World!</Text>
<TouchableHighlight
style={{ ...styles.openButton, backgroundColor: "#2196F3" }}
onPress={() => {
this.setModalVisible(!this.state.modalVisible);
}}
>
<Text style={styles.textStyle}>Hide Modal</Text>
</TouchableHighlight>
</View>
</View>
</Modal>
</View>
);
FirstRoute = () => (
<ScrollView style={[styles.container, { backgroundColor: '#ff4081' }]} >
{this.Modal()}
<TouchableHighlight style={styles.back} onPress={() => {
this.setModalVisible(true);
console.log('Pressed')
}}>
<View style={styles.DisEntry}>
<Text style={styles.text}>{disease[0]}</Text>
<ProgressCircle
percent={30}
radius={50}
borderWidth={8}
color="#3399FF"
shadowColor="#999"
bgColor="#fff"
>
<Text style={{ fontSize: 18 }}>{'30%'}</Text>
</ProgressCircle>
</View>
</TouchableHighlight>
</ScrollView>
);
SecondRoute = () => (
<View style={[styles.container, { backgroundColor: '#673ab7' }]}>
</View>
);
ThirdRoute = () => (
<View style={[styles.container, { backgroundColor: '#673ab7' }]}>
</View>
);
handleSubmit = () => {
addItem(this.state.tagsSelected);
ToastAndroid.show('Symptoms saved successfully', ToastAndroid.SHORT)
};
handleDelete = index => {
let tagsSelected = this.state.tagsSelected;
tagsSelected.splice(index, 1);
this.setState({ tagsSelected });
}
handleAddition = suggestion => {
this.setState({ tagsSelected: this.state.tagsSelected.concat([suggestion]) });
}
_handleIndexChange = index => this.setState({ index });
_renderScene = SceneMap({
first: this.FirstRoute,
second: this.SecondRoute,
third: this.ThirdRoute,
});
render() {
return (
<View style={styles.container}>
<View style={styles.row}>
<View style={styles.autocompleteContainer}>
<AutoTags
suggestions={this.state.storedTags}
tagsSelected={this.state.tagsSelected}
handleAddition={this.handleAddition}
handleDelete={this.handleDelete}
placeholder="Add a Symptom.." />
</View>
<TouchableHighlight
style={styles.button}
underlayColor="blue"
onPress={this.handleSubmit}>
<Text style={styles.buttonText}>Add</Text>
</TouchableHighlight>
</View>
<TabView
style={styles.tab}
navigationState={this.state}
renderScene={this._renderScene}
renderTabBar={this._renderTabBar}
onIndexChange={this._handleIndexChange}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex:1,
},
row:{
flexDirection:"row"
},
DisEntry:{
flexDirection:"row",
backgroundColor:'white',
borderColor: 'black',
borderWidth: 1,
borderRadius: 5,
padding: 2,
},
back:{
backgroundColor: 'blue'
},
text:{
flex:1,
},
button:{
flex:0,
backgroundColor:'white',
borderColor: 'black',
borderWidth: 1,
borderRadius: 5,
padding: 2,
justifyContent:'flex-end',
height:30,
justifyContent:'center',
},
autocompleteContainer: {
flex:1,
justifyContent:'flex-start',
marginBottom:10
},
tab:{
flex:1,
},
centeredView: {
flex: 1,
justifyContent: "center",
alignItems: "center",
marginTop: 22
},
modalView: {
margin: 20,
backgroundColor: "white",
borderRadius: 20,
padding: 35,
alignItems: "center",
shadowColor: "#000",
shadowOffset: {
width: 0,
height: 2
},
shadowOpacity: 0.25,
shadowRadius: 3.84,
elevation: 5
},
openButton: {
backgroundColor: "#F194FF",
borderRadius: 20,
padding: 10,
elevation: 2
},
textStyle: {
color: "white",
fontWeight: "bold",
textAlign: "center"
},
modalText: {
marginBottom: 15,
textAlign: "center"
}
});
I am facing the problem that i am unable to toggle the Modal visibility when i click the touchable highlight. Please tell me where is the issue in my code as when i change the state of my modalVisible to true the modal shows finely
.....................................................................................................
If i'm not mistaken Modal has to be inside of return()
class App extends Component {
state = {
modalVisible: false
};
setModalVisible = (visible) => {
this.setState({ modalVisible: visible });
}
render() {
const { modalVisible } = this.state;
return (
<View style={styles.centeredView}>
<Modal
animationType="slide"
transparent={true}
visible={modalVisible}
onRequestClose={() => {
Alert.alert("Modal has been closed.");
}}
>
<View style={styles.centeredView}>
<View style={styles.modalView}>
<Text style={styles.modalText}>Hello World!</Text>
<TouchableHighlight
style={{ ...styles.openButton, backgroundColor: "#2196F3" }}
onPress={() => {
this.setModalVisible(!modalVisible);
}}
>
<Text style={styles.textStyle}>Hide Modal</Text>
</TouchableHighlight>
</View>
</View>
</Modal>
<TouchableHighlight
style={styles.openButton}
onPress={() => {
this.setModalVisible(true);
}}
>
<Text style={styles.textStyle}>Show Modal</Text>
</TouchableHighlight>
</View>
);
}
}
I am fairly new to React native, and I am looking for a way to have a Drag and Drop Nested List. Basically, I need to create a ToDo list divided in groups, in which the ToDos' order can be changed not only within groups but also among them. I managed to separatly create both a drag & drop list (using the "draggable Flatlist" components) and a nested list, but I am struggling in combining them.
Does anyone solved the issue or knows some kind of reusable component? Thank you.
Try the following:
import React, { useState, useCallback, Component } from 'react';
import { View, TouchableOpacity, Text, SafeAreaView, ScrollView } from 'react-native';
import DraggableFlatList, { RenderItemParams, } from 'react-native-draggable-flatlist';
const Goal_data = [
{
key: "0",
label: "Group",
backgroundColor: "#ababab",
},
{
key: "1",
label: "Group",
backgroundColor: "#ababab",
}
]
const Goal_data1 = [
{
key: "0",
label: "Task",
},
{
key: "1",
label: "Task",
}
]
export default class App extends Component {
constructor(props) {
super(props)
this.state = {
data: Goal_data,
data1: Goal_data1,
scrollEnabled: true
}
}
onEnableScroll = (value) => {
this.setState({
enableScrollViewScroll: value,
});
}
renderItem1 = ({ item, index, drag, isActive }) => {
console.log('index', item)
return (
<TouchableOpacity
style={{
height: 70,
backgroundColor: isActive ? "blue" : item.backgroundColor,
alignItems: "center",
justifyContent: "center"
}}
onLongPress={drag}
>
<Text
style={{
fontWeight: "bold",
color: "white",
fontSize: 20
}}
>
{item.label}
</Text>
</TouchableOpacity>
);
};
plusdata = (data) => {
let d = this.state.data1;
const newRecord = {
key: "2",
label: "Task",
};
this.setState({
data1: [...d, newRecord]
})
}
render() {
return (
<SafeAreaView style={{ flex: 1, }}>
<ScrollView>
<View style={{ backgroundColor: 'aeaeae', flex: 1, paddingHorizontal: 30 }}>
<Text>Hello</Text>
<DraggableFlatList
data={Goal_data}
debug={true}
extraData={Goal_data}
keyExtractor={(item, index) => `draggable-item-${item.key}`}
//onMoveBegin={() => this.setState({ scrollEnabled: false })}
onDragEnd={({ data }) => this.setState({ data: data })}
renderItem={({ item, index, drag, isActive }) => {
console.log('index', item)
return (
<TouchableOpacity
style={{
backgroundColor: isActive ? "blue" : item.backgroundColor,
//alignItems: "center",
justifyContent: "center",
marginVertical: 20
}}
onLongPress={drag}
>
<View style={{ backgroundColor: 'aeaeae', borderColor: '#000', borderWidth: 1, paddingHorizontal: 30 }}>
<Text>{item.label}{index}</Text>
<DraggableFlatList
data={this.state.data1}
extraData={this.state.data1}
debug={true}
keyExtractor={(item, index) => `draggable-item-${index}`}
//onDragEnd={({ data }) => this.setState({ data: data })}
renderItem={({ item, index, drag, isActive }) => {
console.log('index', item)
return (
<TouchableOpacity
style={{
height: 30,
borderBottomWidth: 1,
backgroundColor: isActive ? "blue" : item.backgroundColor,
alignItems: "center",
justifyContent: "center"
}}
onLongPress={drag}
>
<Text
style={{
fontWeight: "bold",
color: "white",
fontSize: 20
}}
>
{item.label}{index}
</Text>
</TouchableOpacity>
);
}}
/>
<TouchableOpacity style={{ marginTop: 50, alignSelf: 'center' }} onPress={() => this.plusdata(Goal_data1)}>
<Text>Add</Text>
</TouchableOpacity>
</View>
</TouchableOpacity>
);
}}
/>
</View>
</ScrollView>
</SafeAreaView>
)
}
}
Hi I have a Home component where I've got a flatlist showing all the users of my application with some infos like the pseudo, their age etc. When we click on a user, it will go to an another component, UserProfil where we can have more infos about the user. I want to implements a swiper that will let me swipe between the users. How can I use my data from Home component in UserProfil in order to start the swiper?
Here are my components :
Home.js
class Accueil extends React.Component {
constructor(props) {
super(props);
this.state = {
loading: false,
refreshing: false,
location: null,
latitude:null,
longitude:null,
dataSource:[],
error:null
}
setInterval(this.displayPosition.bind(this),3000)
this.displayPosition = this.displayPosition.bind(this);
}
getData(){
fetch("someURL")
.then(res => res.json())
.then(res => {
this.setState({
dataSource: res
});
})
.catch(error => {
console.log("get data error:" + error);
}),
{
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
lo: this.state.longitude,
la: this.state.latitude,
}),
}
}
_displayDetailForUser = (idUser, name, photo, age, pratique, description, distance, Statut, localisation, principale ) => {
//console.log("Display user with id " + idUser);
this.props.navigation.navigate("UserProfil", { MembreId: idUser, Pseudo:name, Photo: photo, Age:age, Genre:pratique, Description:description, Distance:distance, Statut:Statut, CP:localisation, Ville:principale });
}
render() {
return (
<SafeAreaView style={{ flex:1 }}>
<View style={styles.main_container}>
<FlatList style={styles.flatList}
data={this.state.dataSource}
extraData = {this.state}
keyExtractor={(item, index) => item.MembreId}
renderItem={(item) => <UserItem user={item} displayDetailForUser={this._displayDetailForUser} />}
numColumns={numColumns}
refreshing={this.state.refreshing}
onRefresh={this.handleRefresh} />
</View>
</SafeAreaView>
)
}
}
and UserProfil
render () {
const { user } = this.props;
var colorConnected;
if (this.props.navigation.getParam('Statut') === "ON") {
colorConnected = "#1fbc26";
}
else if (this.props.navigation.getParam('Statut') === "OFF") {
colorConnected = "#ff0303";
}
else {
colorConnected = "#ffd200";
}
return (
<Swiper showsPagination={false}>
<ScrollView style = {styles.view_container}>
<View style={styles.photo}>
<ImageBackground source={{uri:this.props.navigation.getParam('Photo')}} style={{ width: '100%', height: '100%' }}>
<View style={styles.photo_content}>
<LinearGradient colors={['transparent', 'rgba(0,0,0,0.5)']} style={{ position: 'absolute', left: 0, right: 0, bottom: 0, height: 80 }} />
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
<View>
<Text style={{ fontSize: 40, color:'white' }}>{this.props.navigation.getParam('Age')}</Text>
</View>
<View style={{ marginRight: 7, marginLeft: 7, backgroundColor: '#ffffff', width: 1, height: 39 }}></View>
<View style={{ flexDirection: 'column', flex:1 }}>
<View style={{ flexDirection: 'row' }}>
<View style={[styles.bulle_presence, { backgroundColor: colorConnected } ]}></View>
<Text style={{ fontSize: 18, fontWeight: '600', color:'white' }}>{this.props.navigation.getParam('Pseudo')}</Text>
</View>
<View style={{ flexDirection: 'row', justifyContent: 'space-between'}}>
<Text style={{ fontSize: 15, color:'white' }}>{this.props.navigation.getParam('Distance')}</Text>
<Text style={{ fontSize: 15, color:'white'}}>{this.props.navigation.getParam('Genre')}</Text>
</View>
</View>
</View>
</View>
</ImageBackgroud>
</View>
</ScrollView>
</Swiper>
)}
}
Hi how can I access the state where I'm fetching all the data in an other component ? I have a component Accueil where I'm fetching the data and a component UserItem where I'm styling and showing the info. So I'm in my Accueil component I have a flatlist and inside this flatlist in the renderItem function I'm passing the . So how can I access the state dataSource in UserItem ?
class UserItem extends React.Component {
render() {
const user = this.props.user;
const displayDetailForUser = this.props.displayDetailForUser;
var colorConnected;
if (user.Statut == "ON") {
colorConnected = "#1fbc26";
}
else if (user.Statut == "OFF") {
colorConnected = "#ff0303";
}
else {
colorConnected = "#ffd200";
}
return (
<TouchableOpacity style={styles.view_container} onPress={() =>
displayDetailForUser(user.MembreId, user.Pseudo, user.Photo, user.Age, user.Genre, user.Description, user.distance, user.Statut, user.localisation, user.principale )}>
<ImageBackground source={{ uri : user.Photo}} style={{ flex: 1, aspectRatio: 1, position: 'relative', borderColor: '#d6d6d6', borderWidth: 1}}>
<View style={[styles.bulle_presence, { backgroundColor: colorConnected } ]}></View>
<TouchableOpacity>
<Image style = {{aspectRatio:0.6, position:'absolute', resizeMode:'contain', height:40, width:40, right:15, top:15 }} source = {require("../Images/chat-bg.png")}/>
</TouchableOpacity>
</ImageBackground>
<View style={{ backgroundColor: '#d6d6d6', padding: 6 }}>
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
<View>
<Text style={{ fontSize: 25 }}>{user.Age}</Text>
</View>
<View style={{ marginRight: 7, marginLeft: 7, backgroundColor: '#000000', width: 1, height: 26 }}></View>
<View style={{ flexDirection: 'column', flex:1 }}>
<Text style={{ fontSize: 13, fontWeight: '600' }}>{user.Pseudo}</Text>
<View style={{ flexDirection: 'row', justifyContent: 'space-between'}}>
<Text style={{ fontSize: 12 }}>{user.distance}</Text>
<Text style={{ fontSize: 12 }}>{user.Genre}</Text>
</View>
</View>
</View>
</View>
</TouchableOpacity>
)
}
}
I've tried with const user = this.props.dataSource but it's not working. Thanks
Edit:
lass Accueil extends React.Component {
constructor(props) {
super(props);
this.state = {
loading: false,
refreshing: false,
location: null,
latitude:null,
longitude:null,
dataSource:[]
}
this.displayPosition = this.displayPosition.bind(this);
}
handleRefresh = () => {
this.setState (
{
refreshing: true,
},
() => {
setTimeout(() => {this.setState({refreshing: false,})}, 1000)
}
);
};
componentDidMount() {
const url = "SomeUrl";
fetch(url)
.then(res => res.json())
.then(res => {
this.setState({
dataSource: res
});
})
.catch(error => {
console.log("get data error:" + error);
});
}
static navigationOptions = ({ navigation }) => {
return {
headerRight: () => (
<View style={{marginLeft: 8, marginRight: 8, flexDirection: 'row', alignItems: 'center' }}>
<TouchableOpacity style={{ marginRight: 10 }} onPress={ () =>{ }}>
<Image style={{ width: 22, height: 22 }} source={require("../Images/search.png")} />
</TouchableOpacity>
<TouchableOpacity style={{marginLeft: 10, marginRight: 10 }} onPress={ () =>{{this.displayPosition()}}}>
<Image style={{ width: 22, height: 22 }} source={require("../Images/localisation.png")} />
</TouchableOpacity>
<TouchableOpacity style={{marginLeft: 10 }} onPress={ () =>{ }}>
<Image style={{ width: 22, height: 22 }} source={require("../Images/refresh.png")} />
</TouchableOpacity>
</View>
),
};
};
displayPosition = () => {
Geolocation.getCurrentPosition(
(position) => {
this.setState({
latitude: JSON.stringify(position.coords.latitude),
longitude: JSON.stringify(position.coords.longitude),
error: null,
});
console.log(this.state.latitude)
},
(error) => this.setState({ error: error.message }),
{ enableHighAccuracy: true, timeout: 20000, maximumAge: 1000 },
);
}
_displayDetailForUser = (idUser, name, photo, age, pratique, description, distance, Statut, localisation, principale ) => {
//console.log("Display user with id " + idUser);
this.props.navigation.navigate("UserProfil", { idUser: idUser, name:name, photo: photo, age:age, pratique:pratique, description:description, distance:distance, Statut:Statut, localisation:localisation, principale:principale });
}
render() {
return (
<SafeAreaView style={{ flex:1 }}>
<View style={styles.main_container}>
<FlatList style={styles.flatList}
data={this.state.dataSource}
keyExtractor={(item) => item.MembreId}
renderItem={() => <UserItem user={this.state.dataSource} displayDetailForUser={this._displayDetailForUser} />}
numColumns={numColumns}
refreshing={this.state.refreshing}
onRefresh={this.handleRefresh} />
</View>
</SafeAreaView>
)
}
}
I am using <FlatList/> to render an item for each object of json. This json is stored in this.state.json. Here is my code:
export class MyAppsName extends React.Component {
static navigationOptions = {
title: "App name",
headerLeft: null,
};
constructor() {
super();
this.state = {
index: 0,
isAuthed: false,
data: [
{
name: "Class 1",
grade: 83,
letterGrade: "A+"
},
{
name: "Class 2",
grade: 90,
letterGrade: "B+"
}
],
loading: false
};
}
refresh() {
this.setState({ isAuthed: true });
}
componentWillMount() {
}
render() {
return (
<Root>
<ScrollableTabView initialPage={0} tabBarPosition="top">
<HomeRoute tabLabel="Grades" />
<View
style={{ flex: 1, justifyContent: "center" }}
tabLabel="Settings"
>
</View>
</ScrollableTabView>
</Root>
);
}
}
makeRemoteRequest = () => {
//do request stuff
};
handleRefresh = () => {
this.makeRemoteRequest();
};
renderSeparator = () => {
return (
<View
style={{
height: 1,
width: "86%",
backgroundColor: "black",
}}
/>
);
};
renderHeader = () => {
return <View />;
};
classSelected = className => {
//do stuff
};
renderFooter = () => {
if (!this.state.loading) return null;
return (
<View>
<ActivityIndicator animating size="large" />
</View>
);
};
const HomeRoute = () => (
<List containerStyle={{ borderTopWidth: 0, borderBottomWidth: 0 }}>
<FlatList
style={{ width: width }}
data={this.state.data}
renderItem={({ item }) => (
<View style={{ left: "9%", padding: 6 }}>
<TouchableOpacity onPress={() => this.classSelected(item.name)}>
<Text
style={{
fontSize: 16
}}
>
{item.name}
</Text>
<Text
style={{
fontSize: 12
}}
>
{item.grade}
</Text>
<Text
style={{
fontSize: 12
}}
>
{item.letterGrade}
</Text>
</TouchableOpacity>
</View>
)}
ItemSeparatorComponent={this.renderSeparator}
ListHeaderComponent={this.renderHeader}
ListFooterComponent={this.renderFooter}
keyExtractor={item => item.name}
/>
</List>
);
The error I get is 'TypeError: Cannot read property 'data' of undefined' within HomeRoute. I think the error is in this line: data={this.state.data}.
I am defining data correctly? Am I even correctly setting up the FlatList? Or does it have to do with how I am passing down application state?
If you need any other code to be appended to the question, you can just ask in the comments.
Thanks in advance
You've declared the state in is parent component, causing this.state is undefined in its child component.
When you use the HomeRoute component, you need to pass the state data from its parent component.
render() {
return (
<Root>
<ScrollableTabView initialPage={0} tabBarPosition="top">
<HomeRoute tabLabel="Grades" data={this.state.data} />
<View
style={{ flex: 1, justifyContent: "center" }}
tabLabel="Settings"
>
</View>
</ScrollableTabView>
</Root>
);
}
and in the HomeRoute itself, you need to extract data from its props.
const HomeRoute = ({data}) => (
<List containerStyle={{ borderTopWidth: 0, borderBottomWidth: 0 }}>
<FlatList
style={{ width: width }}
data={data}
renderItem={({ item }) => (
<View style={{ left: "9%", padding: 6 }}>
<TouchableOpacity onPress={() => this.classSelected(item.name)}>
<Text
style={{
fontSize: 16
}}
>
{item.name}
</Text>
<Text
style={{
fontSize: 12
}}
>
{item.grade}
</Text>
<Text
style={{
fontSize: 12
}}
>
{item.letterGrade}
</Text>
</TouchableOpacity>
</View>
)}
ItemSeparatorComponent={this.renderSeparator}
ListHeaderComponent={this.renderHeader}
ListFooterComponent={this.renderFooter}
keyExtractor={item => item.name}
/>
</List>
);
Several functions, including HomeRoute, are not defined within the MyAppsName class. Therefore, this in these functions doesn't point to the correct this. I suggest to put them inside the class and bind all the functions that use this.
You get a syntax error because they are not defined properly. Follow the pattern of the definition of render, for example:
makeRemoteRequest() {
Instead of
makeRemoteRequest = () => {