convert class components to functional components react native - javascript

as i am new in react native. i have no much knowledge of class component. i was stuck in code as class components are used in this code but i want to convert them into functional components. anyone please help me to convert this given code into functional component. this is a code of a swipeable card in react native all the given code in class component and use of constructor and this. i want to just convert it into functional component.
//This is an example of Tinder like Swipeable Card//
import React, { Component } from 'react';
//import react in our code.
import {
Platform, StyleSheet, View, Text,
Dimensions, Animated, PanResponder,
} from 'react-native';
//import all the components we are going to use.
const SCREEN_WIDTH = Dimensions.get('window').width;
class SwipeableCard extends React.Component {
constructor() {
super();
this.panResponder;
this.state = {
Xposition: new Animated.Value(0),
RightText: false,
LeftText: false,
};
this.Card_Opacity = new Animated.Value(1);
this.panResponder = PanResponder.create({
onStartShouldSetPanResponder: (evt, gestureState) => false,
onMoveShouldSetPanResponder: (evt, gestureState) => true,
onStartShouldSetPanResponderCapture: (evt, gestureState) => false,
onMoveShouldSetPanResponderCapture: (evt, gestureState) => true,
onPanResponderMove: (evt, gestureState) => {
this.state.Xposition.setValue(gestureState.dx);
if (gestureState.dx > SCREEN_WIDTH - 250) {
this.setState({
RightText: true,
LeftText: false,
});
} else if (gestureState.dx < -SCREEN_WIDTH + 250) {
this.setState({
LeftText: true,
RightText: false,
});
}
},
onPanResponderRelease: (evt, gestureState) => {
if (
gestureState.dx < SCREEN_WIDTH - 150 &&
gestureState.dx > -SCREEN_WIDTH + 150
) {
this.setState({
LeftText: false,
RightText: false,
});
Animated.spring(
this.state.Xposition,
{
toValue: 0,
speed: 5,
bounciness: 10,
},
{ useNativeDriver: true }
).start();
} else if (gestureState.dx > SCREEN_WIDTH - 150) {
Animated.parallel(
[
Animated.timing(this.state.Xposition, {
toValue: SCREEN_WIDTH,
duration: 200,
}),
Animated.timing(this.Card_Opacity, {
toValue: 0,
duration: 200,
}),
],
{ useNativeDriver: true }
).start(() => {
this.setState({ LeftText: false, RightText: false }, () => {
this.props.removeCard();
});
});
} else if (gestureState.dx < -SCREEN_WIDTH + 150) {
Animated.parallel(
[
Animated.timing(this.state.Xposition, {
toValue: -SCREEN_WIDTH,
duration: 200,
}),
Animated.timing(this.Card_Opacity, {
toValue: 0,
duration: 200,
}),
],
{ useNativeDriver: true }
).start(() => {
this.setState({ LeftText: false, RightText: false }, () => {
this.props.removeCard();
});
});
}
},
});
}
render() {
const rotateCard = this.state.Xposition.interpolate({
inputRange: [-200, 0, 200],
outputRange: ['-20deg', '0deg', '20deg'],
});
return (
<Animated.View
{...this.panResponder.panHandlers}
style={[
styles.card_Style,
{
backgroundColor: this.props.item.backgroundColor,
opacity: this.Card_Opacity,
transform: [
{ translateX: this.state.Xposition },
{ rotate: rotateCard },
],
},
]}>
<Text style={styles.Card_Title}> {this.props.item.card_Title} </Text>
{this.state.LeftText ? (
<Text style={styles.Left_Text_Style}> Left Swipe </Text>
) : null}
{this.state.RightText ? (
<Text style={styles.Right_Text_Style}> Right Swipe </Text>
) : null}
</Animated.View>
);
}
}
export default class App extends React.Component {
constructor() {
super();
this.state = {
Sample_Card_Array: [{
id: '1', card_Title: 'Card 1', backgroundColor: '#FFC107',
}, {
id: '2', card_Title: 'Card 2', backgroundColor: '#ED2525',
}, {
id: '3', card_Title: 'Card 3', backgroundColor: '#E7088E',
}, {
id: '4', card_Title: 'Card 4', backgroundColor: '#00BCD4',
}, {
id: '5', card_Title: 'Card 5', backgroundColor: '#FFFB14',
}],
No_More_Card: false,
};
}
componentDidMount() {
this.setState({
Sample_Card_Array: this.state.Sample_Card_Array.reverse(),
});
if (this.state.Sample_Card_Array.length == 0) {
this.setState({ No_More_Card: true });
}
}
removeCard = id => {
this.state.Sample_Card_Array.splice(
this.state.Sample_Card_Array.findIndex(x => x.id == id),
1
);
this.setState({ Sample_Card_Array: this.state.Sample_Card_Array }, () => {
if (this.state.Sample_Card_Array.length == 0) {
this.setState({ No_More_Card: true });
}
});
};
render() {
return (
<View style={styles.MainContainer}>
{this.state.Sample_Card_Array.map((item, key) => (
<SwipeableCard
key={key}
item={item}
removeCard={this.removeCard.bind(this, item.id)}
/>
))}
{this.state.No_More_Card ? (
<Text style={{ fontSize: 22, color: '#000' }}>No Cards Found.</Text>
) : null}
</View>
);
}
}
const styles = StyleSheet.create({
MainContainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
paddingTop: Platform.OS === 'ios' ? 20 : 0,
},
card_Style: {
width: '75%',
height: '45%',
justifyContent: 'center',
alignItems: 'center',
position: 'absolute',
borderRadius: 7,
},
Card_Title: {
color: '#fff',
fontSize: 24,
},
Left_Text_Style: {
top: 22,
right: 32,
position: 'absolute',
color: '#fff',
fontSize: 20,
fontWeight: 'bold',
backgroundColor: 'transparent',
},
Right_Text_Style: {
top: 22,
left: 32,
position: 'absolute',
color: '#fff',
fontSize: 20,
fontWeight: 'bold',
backgroundColor: 'transparent',
},
});

the part in the render method is what you return.
to create stateObjects in functional components you will need to use the useState method
const functionalComponent = (props)=>{//props are passed in via props arg...
const defaultState = Xposition: new Animated.Value(0),
RightText: false,
LeftText: false
}
const [state,setState] = useState(defaultState);
... // more stuff
return (
<Animated.View
{...this.panResponder.panHandlers}
style={[
styles.card_Style,
{
backgroundColor: props.item.backgroundColor,
opacity: Card_Opacity,
transform: [
{ translateX: state.Xposition },
{ rotate: rotateCard },
],
},
]}>
<Text style={styles.Card_Title}> {props.item.card_Title} </Text>
{this.state.LeftText ? (
<Text style={styles.Left_Text_Style}> Left Swipe </Text>
) : null}
{this.state.RightText ? (
<Text style={styles.Right_Text_Style}> Right Swipe </Text>
) : null}
</Animated.View>
);
}
you should really go watch some videos on useState, you can be much more granular
to set the state you will need to use the setState method returned from the useState call : setState({..state,{XPosition:55}) or something ... you do the ...state to include the old state values, as the state variable will be overwritten with exactly what you pass in... it wont "update" the existing state it will overwrite it
the next bit is hooking into the functionality in componentDidMount you can do this with useEffect
useEffect(()=>{ // this is setup
// do the stuff from componentDidMount
return ()=>{
// any required teardown can be done here
},[] //[] signifies only do this when component mounts... not every update
);// end useEffect componentDidMount
again there is alot more to useEffect, if you want to do stuff when specific state or props are updated

Related

ComponentDidMount vs useEffect

There is a class components work piece. I want to convert it into a function component and implement it in the same way, but there's a problem.
Unlike the class type, the function type returns to the place where it was created without staying after the picture has moved.
This is the function components.
const [dogs, setDogs] = useState([])
function addDog(){
// setDogs([...dogs, {id: dogCount++}])
dogCount++;
console.log(dogCount)
// console.log(dogs)
const newDog = {id: dogCount, bottom: 125}
setDogs([...dogs, newDog])
}
return (
<View style={styles.entirebottomsheet}>
<View style={styles.container}>
<TouchableOpacity onPress={()=>{addDog();}} style={styles.dogButton}>
<Text>Dog</Text>
</TouchableOpacity>
{dogs.map(dog => {
return (
<DogContainer
key={dog.id}
style={{bottom: dog.bottom, position: 'absolute'}}
/>
);
})}
</View>
</View>
);
function DogContainer () {
const positionX = new Animated.Value(0);
const positionY = new Animated.Value(0);
// DogContainer.defaultProps = {
// onComplete() {}
// }
const getDogStyle = () => ({
transform: [{translateX: positionX}],
});
useEffect(() => {
Animated.spring(positionX, {
duration: 1000,
toValue: width / 3,
easing: Easing.ease,
useNativeDriver: true,
}).start();
Animated.spring(positionY, {
duration: 1000,
toValue: width / 3,
easing: Easing.ease,
useNativeDriver: true,
}).start();
return (
console.log('finish')
)
}, []);
return (
<Animated.View style={[{ bottom: 125},{
transform: [{translateX: positionX}, {translateY: positionY}],
}]}>
<Image source={dogImg} style={{width: 60, height: 60}}/>
</Animated.View>
);
}
This is the class components.
export default class App extends React.Component {
// let {up} = this.props.up;
state = {
dogs: [],
cats: [],
chicks: [],
};
addDog = () => {
console.log(...this.state.dogs);
this.setState(
{
dogs: [
...this.state.dogs,
{
id: dogCount,
bottom: 125,
},
],
},
() => {
dogCount++;
},
);
};
removeDog = id => {
this.setState({
dogs: this.state.dogs.filter(dog => {
return dog.id !== id;
}),
});
};
addCat = () => {
console.log(...this.state.cats);
this.setState(
{
cats: [
...this.state.cats,
{
id: catCount,
bottom: 125,
},
],
},
() => {
catCount++;
},
);
};
removeCat = id => {
this.setState({
cats: this.state.cats.filter(cat => {
return cat.id !== id;
}),
});
};
addChick = () => {
console.log(...this.state.chicks);
this.setState(
{
chicks: [
...this.state.chicks,
{
id: chickCount,
bottom: 125,
},
],
},
() => {
chickCount++;
},
);
};
removeChick = id => {
this.setState({
chicks: this.state.chicks.filter(chick => {
return chick.id !== id;
}),
});
};
render() {
return (
<GestureHandlerRootView>
<View style={styles.entirebottomsheet}>
<View style={styles.container}>
<TouchableOpacity onPress={this.addDog} style={styles.dogButton}>
<Text>Dog</Text>
</TouchableOpacity>
{this.state.dogs.map(dog => {
return (
<DogContainer
key={dog.id}
style={{bottom: dog.bottom, position: 'absolute'}}
onComplete={() => this.removeDog(dog.id)}
/>
);
})}
</View>
<View style={styles.container}>
<TouchableOpacity onPress={this.addCat} style={styles.catButton}>
<Text>Cat</Text>
</TouchableOpacity>
{this.state.cats.map(cat => {
return (
<CatContainer
key={cat.id}
style={{bottom: cat.bottom, position: 'absolute'}}
onComplete={() => this.removeCat(cat.id)}
/>
);
})}
</View>
<View style={styles.container}>
<TouchableOpacity onPress={this.addChick} style={styles.chickButton}>
<Text style={{position: 'absolute'}}>Chick</Text>
</TouchableOpacity>
{this.state.chicks.map(chick => {
return (
<ChickContainer
key={chick.id}
style={{bottom: chick.bottom, position: 'absolute'}}
onComplete={() => this.removeChick(chick.id)}
/>
);
})}
</View>
</View>
</GestureHandlerRootView>
);
}
}
class DogContainer extends React.Component {
state = {
position: new Animated.ValueXY({
x: 0,
y: 0,
}),
};
static defaultProps = {
onComplete() {},
};
componentDidMount() {
Animated.spring(this.state.position.x, {
duration: 1000,
toValue: width / 3,
easing: Easing.ease,
useNativeDriver: true,
}).start(this.props.onComplete);
Animated.spring(this.state.position.y, {
duration: 1000,
toValue: -340,
easing: Easing.ease,
useNativeDriver: true,
}).start(this.props.onComplete);
}
getDogStyle() {
return {
transform: [
{translateY: this.state.position.y},
{translateX: this.state.position.x},
],
};
}
render() {
return (
<Animated.View style={[this.getDogStyle(), this.props.style]}>
<Image source={dogImg} style={{width: 60, height: 60, borderRadius: 30}} />
</Animated.View>
);
}
}
Try to use useRef() hook
function DogContainer () {
const positionX = useRef(new Animated.Value(0)).current;
const positionY = useRef(new Animated.Value(0)).current;
...
In the Class-based version of DogContainer the position coordinate was a part of state.
class DogContainer extends React.Component {
state = {
position: new Animated.ValueXY({
x: 0,
y: 0,
}),
};
static defaultProps = {
onComplete() {},
};
componentDidMount() {
Animated.spring(this.state.position.x, {
duration: 1000,
toValue: width / 3,
easing: Easing.ease,
useNativeDriver: true,
}).start(this.props.onComplete);
Animated.spring(this.state.position.y, {
duration: 1000,
toValue: -340,
easing: Easing.ease,
useNativeDriver: true,
}).start(this.props.onComplete);
}
getDogStyle() {
return {
transform: [
{translateY: this.state.position.y},
{translateX: this.state.position.x},
],
};
}
render() {
return (
<Animated.View style={[this.getDogStyle(), this.props.style]}>
<Image source={dogImg} style={{width: 60, height: 60, borderRadius: 30}} />
</Animated.View>
);
}
}
Function component using the useState hook
function DogContainer ({ onComplete = () => {} }) {
const [position, setPosition] = React.useState(
new Animated.ValueXY({
x: 0,
y: 0,
})
);
const getDogStyle = () => ({
transform: [{
translateX: position.x,
translateY: position.y,
}],
});
useEffect(() => {
Animated.spring(position.x, {
duration: 1000,
toValue: width / 3,
easing: Easing.ease,
useNativeDriver: true,
}).start(onComplete);
Animated.spring(position.y, {
duration: 1000,
toValue: width / 3,
easing: Easing.ease,
useNativeDriver: true,
}).start(onComplete);
console.log('finish');
}, []);
return (
<Animated.View
style={[
{ bottom: 125},
{ transform: [
{ translateX: position.x },
{ translateY: position.y }
],
}
]}
>
<Image source={dogImg} style={{ width: 60, height: 60 }} />
</Animated.View>
);
}

Delete List Item on right swipe react-native

// Here I am trying to delete List item from Flat List .
Data is populating from JSON on Flat List now I have to delete particular list item data form list , for that I am using "Swipeout" . but getting error "Type error: undefined is not an object(evaluting this.2.viewNote.bind")
Please help . Where am going wrong and how can I do this
import React, { Component } from 'react';
import { View, Text, TextInput,
FooterTab,Button,TouchableOpacity, ScrollView, StyleSheet,
ActivityIndicator ,Header,FlatList} from 'react-native';
import {Icon} from 'native-base';
import { Table, Row, Rows } from 'react-native-table-component';
import { createStackNavigator } from 'react-navigation';
import { SearchBar } from 'react-native-elements';
import Swipeout from 'react-native-swipeout';
let swipeBtns = [{
text: 'Delete',
backgroundColor: 'red',
underlayColor: 'rgba(0, 0, 0, 1, 0.6)',
onPress: () => { this.deleteNote(item) }
}];
export default class OpenApplianceIssue extends Component {
constructor() {
super();
this.state = {
AbcSdata: null,
loading: true,
search: '',
tableData: [], qrData: '', selectedPriority: '',
selectedIssue: '', selectedReason: '', selectedTriedRestart: '',
selectedPowerLED: '', selectedBurning: '', selectedNoise: '',
};
this.setDate = this.setDate.bind(this);
}
setDate(newDate) {
}
_loadInitialState = async () => {
const { navigation } = this.props;
const qdata = navigation.getParam('data', 'NA').split(',');
var len = qdata.length;
const tData = [];
console.log(len);
for(let i=0; i<len; i++)
{
var data = qdata[i].split(':');
const entry = []
entry.push(`${data[0]}`);
entry.push(`${data[1]}`);
tData.push(entry);
}
this.setState({tableData: tData } );
console.log(this.state.tableData);
this.setState({loading: true});
}
componentDidMount() {
this._loadInitialState().done();
this.createViewGroup();
}
createViewGroup = async () => {
try {
const response = await fetch(
'http:/Dsenze/userapi/sensor/viewsensor',
{
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
"password": 'admin',
"username": 'admin',
"startlimit":"0",
"valuelimit":"10",
}),
}
);
const responseJson = await response.json();
const { sensorData } = responseJson;
this.setState({
AbcSdata: sensorData,
loading: false,
});
} catch (e) {
console.error(e);
}
};
updateSearch = search => {
this.setState({ search });
};
keyExtractor = ({ id }) => id.toString();
keyExtractor = ({ inventory }) => inventory.toString();
renderItem = ({ item }) => (
<Swipeout right={swipeBtns}>
<TouchableOpacity
style={styles.item}
activeOpacity={0.4}
onPress={this.viewNote.bind(this, item)} >
<Text >Id : {item.id}</Text>
<Text>Inventory : {item.inventory}</Text>
<Text>SensorType : {item.sensorType}</Text>
<Text>TypeName : {item.typeName}</Text>
</TouchableOpacity>
</Swipeout>
);
viewNote(item) {
this.props.navigator.push({
title: 'The Note',
component: ViewNote,
passProps: {
noteText: item,
noteId: this.noteId(item),
}
});
}
onClickListener = (viewId) => {
if(viewId == 'tag')
{
this.props.navigation.navigate('AddSensors');
}}
renderSeparator = () => {
return (
<View
style={{
height: 1,
width: "86%",
backgroundColor: "#CED0CE",
}}
/>
);
};
render() {
const { loading, AbcSdata } = this.state;
const state = this.state;
return (
<ScrollView>
<View style={styles.container1}>
<Button full rounded
style={{fontSize: 20, color: 'green'}}
styleDisabled={{color: 'red'}}
onPress={() => this.onClickListener('tag')}
title="Add Sensors"
>
Add Sensors
</Button>
</View>
<View style={styles.container1}>
{this.state.loading ? (
<ActivityIndicator size="large" />
) :
(
<FlatList
data={AbcSdata}
renderItem={this.renderItem}
keyExtractor={this.keyExtractor}
ItemSeparatorComponent={this.renderSeparator}
/>
)}
</View>
<View>
<Text
style={{alignSelf: 'center', fontWeight: 'bold', color: 'black'}} >
Inventory Details
</Text>
<Table borderStyle={{borderWidth: 2, borderColor: '#c8e1ff', padding:10,paddingBottom: 10}}>
<Rows data={state.tableData} textStyle={styles.text}/>
</Table>
</View>
</ScrollView>
);
}
}
const styles = StyleSheet.create(
{
container1:
{
flex: 1,
alignItems: 'stretch',
fontFamily: "vincHand",
color: 'blue'
},
header_footer_style:{
width: '100%',
height: 44,
backgroundColor: '#4169E1',
alignItems: 'center',
justifyContent: 'center',
color:'#ffffff',
},
Progressbar:{
justifyContent: 'center',
alignItems: 'center',
color: 'blue',
},
ListContainer :{
borderColor: '#48BBEC',
backgroundColor: '#000000',
color:'red',
alignSelf: 'stretch' ,
},
container2:
{
flex: 1,
justifyContent: 'center',
alignItems: 'stretch',
paddingHorizontal: 15
},
inputBox:{
width:300,
borderColor: '#48BBEC',
backgroundColor: '#F8F8FF',
borderRadius:25,
paddingHorizontal:16,
fontSize:16,
color:'#000000',
marginVertical:10,
},
button:{
width:300,
backgroundColor:'#4169E1',
borderRadius:25,
marginVertical:10,
paddingVertical:16
},
buttonText:{
fontSize:16,
fontWeight:'500',
color:'#ffffff',
textAlign:'center'
},
textStyle:{
fontSize:16,
fontWeight:'500',
color:'#ffffff',
textAlign:'center'
},
item:
{
padding: 15
},
text:
{
fontSize: 18
},
button:{
width:300,
backgroundColor:'#4169E1',
borderRadius:25,
marginVertical:10,
paddingVertical:16
},
buttonText:{
fontSize:16,
fontWeight:'500',
color:'red',
textAlign:'center'
},
separator:
{
height: 2,
backgroundColor: 'rgba(0,0,0,0.5)'
},
container: { flex: 1, padding: 16, paddingTop: 30, backgroundColor: '#fff' },
head: { height: 40, backgroundColor: '#f1f8ff' },
text: { margin: 6 }
});
Thanks .
First thing first,
Try using fat-arrow functions whenever possible, which will automatically solve your binding issues.
You will have to use the extraData= {this.state.activeRow} in your flatlist with newly added state activeRow.
I have updated your renderItem().
Check out the following updated code. Hope this helps.
import * as React from 'react';
import { View, Text, TextInput,
FooterTab, Button, TouchableOpacity, ScrollView, StyleSheet,
ActivityIndicator, Header, FlatList } from 'react-native';
import { Table, Row, Rows } from 'react-native-table-component';
import { createStackNavigator } from 'react-navigation';
import { SearchBar } from 'react-native-elements';
import { Constants } from 'expo';
// You can import from local files
import AssetExample from './components/AssetExample';
// or any pure javascript modules available in npm
import { Card } from 'react-native-paper';
import Swipeout from 'react-native-swipeout';
export default class App extends React.Component {
constructor() {
super();
this.state = {
AbcSdata: null,
loading: true,
search: '',
tableData: [], qrData: '', selectedPriority: '',
selectedIssue: '', selectedReason: '', selectedTriedRestart: '',
selectedPowerLED: '', selectedBurning: '', selectedNoise: '',
rowID:'',
activeRow: null
};
this.setDate = this.setDate.bind(this);
}
swipeBtns = [{
text: 'Delete',
type: 'delete',
backgroundColor: 'red',
underlayColor: 'rgba(0, 0, 0, 1, 0.6)',
onPress: () => {
console.log("Deleting Row with Id ", this.state.activeRow);
this.deleteNote(this.state.activeRow);
}
}];
removeItem = (items, i) =>
items.slice(0, i).concat(items.slice(i + 1, items.length));
deleteNote = (rowIndex) => {
//add your custome logic to delete the array element with index.
// this will temporary delete from the state.
let filteredData = this.removeItem(this.state.AbcSdata,rowIndex);
this.setState({AbcSdata: [] },()=> {
this.setState({AbcSdata: filteredData },()=> {console.log("Row deleted.", rowIndex)});
});
};
setDate(newDate) {
}
_loadInitialState = async () => {
const { navigation } = this.props;
const qdata = navigation.getParam('data', 'NA').split(',');
var len = qdata.length;
const tData = [];
console.log(len);
for (let i = 0; i < len; i++) {
var data = qdata[i].split(':');
const entry = []
entry.push(`${data[0]}`);
entry.push(`${data[1]}`);
tData.push(entry);
}
this.setState({ tableData: tData });
console.log(this.state.tableData);
this.setState({ loading: true });
}
componentDidMount() {
//this._loadInitialState().done();
this.createViewGroup();
}
createViewGroup = async () => {
try {
const response = await fetch(
'/Dsenze/userapi/sensor/viewsensor',
{
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
"password": 'admin',
"username": 'admin',
"startlimit": "0",
"valuelimit": "10",
}),
}
);
const responseJson = await response.json();
const { sensorData } = responseJson;
this.setState({
AbcSdata: sensorData,
loading: false,
});
} catch (e) {
console.error(e);
}
};
updateSearch = search => {
this.setState({ search });
};
keyExtractor = ({ id }) => id.toString();
keyExtractor = ({ inventory }) => inventory.toString();
onSwipeOpen(rowId, direction) {
if(typeof direction !== 'undefined'){
this.setState({activeRow:rowId});
console.log("Active Row",rowId);
}
}
renderItem = ({ item, index }) => (
<Swipeout
right={this.swipeBtns}
close={(this.state.activeRow !== index)}
rowID={index}
sectionId= {1}
autoClose = {true}
onOpen = {(secId, rowId, direction) => this.onSwipeOpen(rowId, direction)}
>
<TouchableOpacity
style={styles.item}
activeOpacity={0.4}
onPress={this.viewNote(item)} >
<Text >Id : {item.id}</Text>
<Text>Inventory : {item.inventory}</Text>
<Text>SensorType : {item.sensorType}</Text>
<Text>TypeName : {item.typeName}</Text>
</TouchableOpacity>
</Swipeout>
);
viewNote =(item) => {
this.props.navigator.push({
title: 'The Note',
component: this.ViewNote,
passProps: {
noteText: item,
noteId: this.noteId(item),
}
});
console.log("View Note Success");
}
onClickListener = (viewId) => {
if (viewId == 'tag') {
this.props.navigation.navigate('AddSensors');
}
}
renderSeparator = () => {
return (
<View
style={{
height: 1,
width: "86%",
backgroundColor: "#CED0CE",
}}
/>
);
};
render() {
const { loading, AbcSdata } = this.state;
const state = this.state;
return (
<ScrollView>
<View style={styles.container1}>
<Button full rounded
style={{ fontSize: 20, color: 'green' }}
styleDisabled={{ color: 'red' }}
onPress={() => this.onClickListener('tag')}
title="Add Sensors"
>
Add Sensors
</Button>
</View>
<View style={styles.container1}>
{this.state.loading ? (
<ActivityIndicator size="large" />
) :
(
<FlatList
data={AbcSdata}
renderItem={this.renderItem}
keyExtractor={this.keyExtractor}
extraData= {this.state.activeRow}
ItemSeparatorComponent={this.renderSeparator}
/>
)}
</View>
<View>
<Text
style={{ alignSelf: 'center', fontWeight: 'bold', color: 'black' }} >
Inventory Details
</Text>
<Table borderStyle={{ borderWidth: 2, borderColor: '#c8e1ff', padding: 10, paddingBottom: 10 }}>
<Rows data={state.tableData} textStyle={styles.text} />
</Table>
</View>
</ScrollView>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
padding: 8,
},
paragraph: {
margin: 24,
fontSize: 18,
fontWeight: 'bold',
textAlign: 'center',
},
});

react-native can't open expo project

I am trying to run an expo project Collapsible Header with TabView it works fine in this link.
But when I copy and paste the code to my own expo project, it gives me an error.
Invariant Violation: Element type is invalid: expected a string or a class/function. Check the render method of App
The only thing I changed is class TabView to class App but it is giving me this error.
Also, if I want to build a native code project not expo. How would I run this code? because there is import {Constants } from expo this wouldn't work in react-native run-ios
import * as React from 'react';
import {
View,
StyleSheet,
Dimensions,
ImageBackground,
Animated,
Text
} from 'react-native';
import { Constants } from 'expo';
import { TabViewAnimated, TabBar } from 'react-native-tab-view'; // Version can be specified in package.json
import ContactsList from './components/ContactsList';
const initialLayout = {
height: 0,
width: Dimensions.get('window').width,
};
const HEADER_HEIGHT = 240;
const COLLAPSED_HEIGHT = 52 + Constants.statusBarHeight;
const SCROLLABLE_HEIGHT = HEADER_HEIGHT - COLLAPSED_HEIGHT;
export default class TabView extends React.Component {
constructor(props: Props) {
super(props);
this.state = {
index: 0,
routes: [
{ key: '1', title: 'First' },
{ key: '2', title: 'Second' },
{ key: '3', title: 'Third' },
],
scroll: new Animated.Value(0),
};
}
_handleIndexChange = index => {
this.setState({ index });
};
_renderHeader = props => {
const translateY = this.state.scroll.interpolate({
inputRange: [0, SCROLLABLE_HEIGHT],
outputRange: [0, -SCROLLABLE_HEIGHT],
extrapolate: 'clamp',
});
return (
<Animated.View style={[styles.header, { transform: [{ translateY }] }]}>
<ImageBackground
source={{ uri: 'https://picsum.photos/900' }}
style={styles.cover}>
<View style={styles.overlay} />
<TabBar {...props} style={styles.tabbar} />
</ImageBackground>
</Animated.View>
);
};
_renderScene = () => {
return (
<ContactsList
scrollEventThrottle={1}
onScroll={Animated.event(
[{ nativeEvent: { contentOffset: { y: this.state.scroll } } }],
{ useNativeDriver: true }
)}
contentContainerStyle={{ paddingTop: HEADER_HEIGHT }}
/>
);
};
render() {
return (
<TabViewAnimated
style={styles.container}
navigationState={this.state}
renderScene={this._renderScene}
renderHeader={this._renderHeader}
onIndexChange={this._handleIndexChange}
initialLayout={initialLayout}
/>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
overlay: {
flex: 1,
backgroundColor: 'rgba(0, 0, 0, .32)',
},
cover: {
height: HEADER_HEIGHT,
},
header: {
position: 'absolute',
top: 0,
left: 0,
right: 0,
zIndex: 1,
},
tabbar: {
backgroundColor: 'rgba(0, 0, 0, .32)',
elevation: 0,
shadowOpacity: 0,
},
});
I got it worked! I had to replace TabViewAnimated to TabView.

How to get and pass the details of the active slide in react native using react-native-snap-carousel

I need to pass the details of the currently active slide to another js file. how can I do this (there are 8 slides)?
The details that I need to pass is the slide's name and Index,
Here is my carousel js file :
import React, { Component } from 'react';
import { Dimensions, View, Image } from 'react-native';
import Carousel from 'react-native-snap-carousel';
const { height, width } = Dimensions.get('window');
class TeamScroll extends Component {
render() {
return (
<View >
<View style={{ transform: [{ rotate: '-14deg' }] }}>
<Carousel
ref={(c) => { this.props.carouselRef = c; }}
inactiveSlideOpacity={0.6}
inactiveSlideScale={0.65}
firstItem={1}
sliderWidth={width}
itemWidth={width / 3} >
<Image
source={require('./Images/logo-chepauk.png')}
style={styles.logoStyle} />
<Image
source={require('./Images/logo-dindigul.png')}
style={styles.logoStyle} />
<Image
source={require('./Images/logo-kanchi.png')}
style={styles.logoStyle} />
<Image
source={require('./Images/logo-karaikudi.png')}
style={styles.logoStyle} />
<Image
source={require('./Images/logo-kovai.png')}
style={styles.logoStyle} />
<Image
source={require('./Images/logomadurai.png')}
style={styles.logoStyle} />
<Image
source={require('./Images/logothiruvallur.png')}
style={styles.logoStyle} />
<Image
source={require('./Images/logotuti.png')}
style={styles.logoStyle} />
</Carousel>
</View>
</View>
);
}
}
const styles = {
logoStyle: {
transform: [{ rotate: '14deg' }],
width: width / 3,
height: width / 3
}
};
export default TeamScroll;
Here is one of the files where I need to use these details
import React, { Component } from 'react';
import { Image, Text, View, TouchableWithoutFeedback, Animated, Dimensions } from 'react-native';
import { Actions } from 'react-native-router-flux';
import TeamScroll from './TeamScroll';
const a = require('./Images/over3_selected.png');
const b = require('./Images/over3.png');
const c = require('./Images/over5_selected.png');
const d = require('./Images/over5.png');
const e = require('./Images/over10_selected.png');
const f = require('./Images/over10.png');
const Sound = require('react-native-sound');
const btnSound = new Sound('btn_sound.mp3', Sound.MAIN_BUNDLE);
const w = Dimensions.get('window').width;
const h = Dimensions.get('window').height;
class ChallengeScreen extends Component {
state = {
threePressed: false,
fivePressed: false,
tenPressed: false,
}
componentWillMount() {
this.slide1 = new Animated.Value(0);
this.slide2 = new Animated.Value(0);
this.slide3 = new Animated.Value(0);
this.ball1();
this.ball2();
this.ball3();
}
ball1() {
Animated.timing(
this.slide1, {
delay: 100,
toValue: -(w / 2.57),
duration: 700,
}
).start();
}
ball2() {
Animated.timing(
this.slide2, {
delay: 200,
toValue: -(w / 2.25),
duration: 900,
}
).start();
}
ball3() {
Animated.timing(
this.slide3, {
delay: 300,
toValue: -(w / 2),
duration: 1100,
}
).start();
}
render() {
return (
<Image
source={require('./Images/bg_inner.png')} style={styles.backgroundStyle}>
<Text style={styles.chooseteamtextStyle}>
CHOOSE YOUR TEAM
</Text>
<Image source={require('./Images/team-logo-band.png')} style={styles.band1Style}>
<TeamScroll carouselRef />
</Image>
<Text style={styles.opponentStyle}>
YOUR OPPONENT
</Text>
<Image source={require('./Images/team-logo-band.png')} style={styles.band2Style}>
<TeamScroll carouselRef />
</Image>
<Text style={styles.overstextStyle}>
OVERS
</Text>
<View style={styles.viewStyle}>
<TouchableWithoutFeedback
onPress={() => {
btnSound.play();
playFunc(3, this.props.challenge); }
}
onPressIn={() => {
this.setState({ threePressed: true });
}}
onPressOut={() => {
this.setState({ threePressed: false });
}}
>
<Animated.Image source={this.state.threePressed ? a : b}
style={[styles.over3Style, { transform: [{ translateY: this.slide1 }] }]} />
</ TouchableWithoutFeedback>
<TouchableWithoutFeedback
onPress={() => {
btnSound.play();
playFunc(5, this.props.challenge); }
}
onPressIn={() => {
this.setState({ fivePressed: true });
}}
onPressOut={() => {
this.setState({ fivePressed: false });
}}>
<Animated.Image source={this.state.fivePressed ? c : d}
style={[styles.over5Style, { transform: [{ translateY: this.slide2 }] }]} />
</ TouchableWithoutFeedback>
<TouchableWithoutFeedback
onPress={() => {
btnSound.play();
playFunc(10, this.props.challenge); }
}
onPressIn={() => {
this.setState({ tenPressed: true });
}}
onPressOut={() => {
this.setState({ tenPressed: false });
}}>
<Animated.Image source={this.state.tenPressed ? e : f}
style={[styles.over10Style, { transform: [{ translateY: this.slide3 }] }]} />
</ TouchableWithoutFeedback>
</View>
</ Image>
);
}
}
function playFunc(num, param) {
if (num === 3 && param === 'Computer') {
Actions.screen4({ balls: 18 });
}
else if (num === 5 && param === 'Computer') {
Actions.screen4({ balls: 30 });
}
else if (num === 10 && param === 'Computer') {
Actions.screen4({ balls: 60 });
}
else if (num === 3 && param === 'Team') {
Actions.screen3({ balls: 18 });
}
else if (num === 5 && param === 'Team') {
Actions.screen3({ balls: 30 });
}
else if (num === 10 && param === 'Team') {
Actions.screen3({ balls: 60 });
}
}
const styles = {
viewStyle: {
flexDirection: 'row',
justifyContent: 'flex-start'
},
backgroundStyle: {
flex: 1,
width: w,
height: h,
flexWrap: 'wrap',
},
chooseteamtextStyle: {
textAlign: 'center',
marginTop: h / 6.57,
fontSize: 22,
color: 'white',
fontFamily: 'Switzerland-Cond-Black-Italic',
transform: [{ rotate: '-14deg' }]
},
band1Style: {
resizeMode: 'stretch',
width: (w / 0.947),
height: (h / 3.93),
},
opponentStyle: {
textAlign: 'center',
marginTop: -(h / 59.2),
fontSize: 22,
color: 'white',
fontFamily: 'Switzerland-Cond-Black-Italic',
transform: [{ rotate: '-15deg' }]
},
band2Style: {
resizeMode: 'stretch',
width: (w / 0.947),
height: (h / 4),
},
overstextStyle: {
textAlign: 'center',
bottom: (h / 59.2),
fontSize: 22,
color: 'white',
fontFamily: 'Switzerland-Cond-Black-Italic',
transform: [{ rotate: '-15deg' }]
},
over3Style: {
flexDirection: 'row',
alignItems: 'flex-start',
width: (w / 4.5),
height: (h / 7.4),
top: (h / 3.482),
left: (w / 5.142),
},
over5Style: {
flexDirection: 'row',
alignItems: 'center',
width: (w / 4.5),
height: (h / 7.4),
bottom: -(h / 3.48),
left: (h / 8.45)
},
over10Style: {
flexDirection: 'row',
alignItems: 'flex-end',
width: (w / 4.5),
height: (h / 7.4),
top: (h / 3.48),
right: -(w / 5.42)
}
};
export default ChallengeScreen;
I have tried using state and props for doing it, and also using getters like currentIndex using carousel's reference but couldn't get the details
What about adding a dedicated prop to <TeamScroll />?
TeamScroll.js
class TeamScroll extends Component {
static propTypes = {
snapCallback: PropTypes.func
}
static defaultProps = {
snapCallback: () => {}
}
constructor (props) {
super(props);
this._onSnapToItem = this._onSnapToItem.bind(this);
}
_onSnapToItem (index) {
this.props.snapCallback(index, this.state.customData);
}
render() {
return (
<View >
<View style={{ transform: [{ rotate: '-14deg' }] }}>
<Carousel onSnapToItem={this._onSnapToItem}>
// images
</Carousel>
</View>
</View>
);
}
}
ChallengeScreen.js
class ChallengeScreen extends Component {
onSnap (index, data) {
console.log('CAROUSEL INDEX', { index, data });
}
render() {
return (
<Image source={require('./Images/team-logo-band.png')} style={styles.band2Style}>
<TeamScroll carouselRef snapCallback={onSnap} />
</Image>
);
}
}
I'm using this
class TeamScroll extends Component {
constructor(props) {
super(props);
this.state = {
currentIndex: 0,
};
}
changePage(nextIndex, isLast) {
this.setState({ currentIndex: nextIndex });
this.props.onChangePage(nextIndex + 1, isLast);
}
render() {
return (
<Page>
<Carousel
ref={(carousel) => { this.carousel = carousel; }}
firstItem={this.state.currentIndex}
onSnapToItem={(index) => this.changePage(index, index === screens.length - 1)}
data={screens}
renderItem={this.renderCarouselItem}
/>
);
}
}
Note that I'm using the new syntax introduced in version 3, but it works as well in version 2.
The class has onChangePage prop that gets called when you snap to another item.
You can use the onChangePage with
<TeamScroll onChangePage={(pageIndex, isLastPage) => {
// do something here, maybe
this.setState({ currentPage: pageIndex });
}} />

How do I port an iOS index file in react native to android

I have the following code for my index.io.js file. I am new to react native and don't quite know how to port it to index.android.js. Is there a certain standard that I can follow to migrate this to the android version? What needs to be done exactly?
'use strict';
var ShakeEvent = require('react-native-shake-event-ios');
var NetworkImage = require('react-native-image-progress');
var Progress = require('react-native-progress');
var Swiper = require('react-native-swiper');
var RandManager = require('./RandManager.js');
var Utils = require('./Utils.js');
var React = require('react-native');
// Components
var ProgressHUD = require('./ProgressHUD.js');
var {
AppRegistry,
StyleSheet,
Text,
View,
Component,
ActivityIndicatorIOS,
Dimensions,
PanResponder,
CameraRoll,
AlertIOS
} = React;
var {width, height} = Dimensions.get('window');
const NUM_WALLPAPERS = 5;
const DOUBLE_TAP_DELAY = 300; // milliseconds
const DOUBLE_TAP_RADIUS = 20;
class SplashWalls extends Component{
constructor(props) {
super(props);
this.state = {
wallsJSON: [],
isLoading: true,
isHudVisible: false
};
this.imagePanResponder = {};
// Previous touch information
this.prevTouchInfo = {
prevTouchX: 0,
prevTouchY: 0,
prevTouchTimeStamp: 0
};
this.currentWallIndex = 0;
// Binding this to methods
this.handlePanResponderGrant = this.handlePanResponderGrant.bind(this);
this.onMomentumScrollEnd = this.onMomentumScrollEnd.bind(this);
}
componentDidMount() {
this.fetchWallsJSON();
}
componentWillMount() {
this.imagePanResponder = PanResponder.create({
onStartShouldSetPanResponder: this.handleStartShouldSetPanResponder,
onPanResponderGrant: this.handlePanResponderGrant,
onPanResponderRelease: this.handlePanResponderEnd,
onPanResponderTerminate: this.handlePanResponderEnd
});
// Fetch new wallpapers on shake
ShakeEvent.addEventListener('shake', () => {
this.initialize();
this.fetchWallsJSON();
});
}
render() {
var {isLoading} = this.state;
if(isLoading)
return this.renderLoadingMessage();
else
return this.renderResults();
}
initialize() {
this.setState({
wallsJSON: [],
isLoading: true,
isHudVisible: false
});
this.currentWallIndex = 0;
}
fetchWallsJSON() {
var url = 'http://unsplash.it/list';
fetch(url)
.then( response => response.json() )
.then( jsonData => {
var randomIds = RandManager.uniqueRandomNumbers(NUM_WALLPAPERS, 0, jsonData.length);
var walls = [];
randomIds.forEach(randomId => {
walls.push(jsonData[randomId]);
});
this.setState({
isLoading: false,
wallsJSON: [].concat(walls)
});
})
.catch( error => console.log('JSON Fetch error : ' + error) );
}
renderLoadingMessage() {
return (
<View style={styles.loadingContainer}>
<ActivityIndicatorIOS
animating={true}
color={'#fff'}
size={'small'}
style={{margin: 15}} />
<Text style={{color: '#fff'}}>Contacting Unsplash</Text>
</View>
);
}
saveCurrentWallpaperToCameraRoll() {
// Make Progress HUD visible
this.setState({isHudVisible: true});
var {wallsJSON} = this.state;
var currentWall = wallsJSON[this.currentWallIndex];
var currentWallURL = `http://unsplash.it/${currentWall.width}/${currentWall.height}?image=${currentWall.id}`;
CameraRoll.saveImageWithTag(currentWallURL, (data) => {
// Hide Progress HUD
this.setState({isHudVisible: false});
AlertIOS.alert(
'Saved',
'Wallpaper successfully saved to Camera Roll',
[
{text: 'High 5!', onPress: () => console.log('OK Pressed!')}
]
);
},(err) =>{
console.log('Error saving to camera roll', err);
});
}
onMomentumScrollEnd(e, state, context) {
this.currentWallIndex = state.index;
}
renderResults() {
var {wallsJSON, isHudVisible} = this.state;
return (
<View>
<Swiper
dot={<View style={{backgroundColor:'rgba(255,255,255,.4)', width: 8, height: 8,borderRadius: 10, marginLeft: 3, marginRight: 3, marginTop: 3, marginBottom: 3,}} />}
activeDot={<View style={{backgroundColor: '#fff', width: 13, height: 13, borderRadius: 7, marginLeft: 7, marginRight: 7}} />}
onMomentumScrollEnd={this.onMomentumScrollEnd}
index={this.currentWallIndex}
loop={false}>
{wallsJSON.map((wallpaper, index) => {
return(
<View key={wallpaper.id}>
<NetworkImage
source={{uri: `https://unsplash.it/${wallpaper.width}/${wallpaper.height}?image=${wallpaper.id}`}}
indicator={Progress.Circle}
indicatorProps={{
color: 'rgba(255, 255, 255)',
size: 60,
thickness: 7
}}
threshold={0}
style={styles.wallpaperImage}
{...this.imagePanResponder.panHandlers}>
<Text style={styles.label}>Photo by</Text>
<Text style={styles.label_authorName}>{wallpaper.author}</Text>
</NetworkImage>
</View>
);
})}
</Swiper>
<ProgressHUD width={width} height={height} isVisible={isHudVisible}/>
</View>
);
}
// Pan Handler methods
handleStartShouldSetPanResponder(e, gestureState){
return true;
}
handlePanResponderGrant(e, gestureState) {
var currentTouchTimeStamp = Date.now();
if( this.isDoubleTap(currentTouchTimeStamp, gestureState) )
this.saveCurrentWallpaperToCameraRoll();
this.prevTouchInfo = {
prevTouchX: gestureState.x0,
prevTouchY: gestureState.y0,
prevTouchTimeStamp: currentTouchTimeStamp
};
}
handlePanResponderEnd(e, gestureState) {
// When finger is pulled up from the screen
}
isDoubleTap(currentTouchTimeStamp, {x0, y0}) {
var {prevTouchX, prevTouchY, prevTouchTimeStamp} = this.prevTouchInfo;
var dt = currentTouchTimeStamp - prevTouchTimeStamp;
return (dt < DOUBLE_TAP_DELAY && Utils.distance(prevTouchX, prevTouchY, x0, y0) < DOUBLE_TAP_RADIUS);
}
};
var styles = StyleSheet.create({
loadingContainer: {
flexDirection: 'row',
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#000'
},
wallpaperImage: {
flex: 1,
width: width,
height: height,
backgroundColor: '#000'
},
label: {
position: 'absolute',
color: '#fff',
fontSize: 13,
backgroundColor: 'rgba(0, 0, 0, 0.8)',
padding: 2,
paddingLeft: 5,
top: 20,
left: 20,
width: width/2
},
label_authorName: {
position: 'absolute',
color: '#fff',
fontSize: 15,
backgroundColor: 'rgba(0, 0, 0, 0.8)',
padding: 2,
paddingLeft: 5,
top: 41,
left: 20,
fontWeight: 'bold',
width: width/2
}
});
AppRegistry.registerComponent('SplashWalls', () => SplashWalls);
Copy content of index.ios.js to index.android.js first. If it does not contain any iOS specific code/libs, it will just work. If not, go to step 2.
Adjust code to use Android specific code, or lib API - if such code exists. If not, go to step 3.
Either swap iOS code/libs for Android ones, or write required code yourself.

Categories

Resources