React native simple animation - react-native

Hi I just want to make simple starter game. Rock paper scissors. This code is all I do.
I just want to animate the image and the text on every buttonpress.
Image is animating once, when press the button stops animating.
How can I show the image with animation every button press
I'm using the react-native-animatable library from npm.Also you can suggest me another
import React from 'react';
import { View, Text, TouchableOpacity, Image } from 'react-native';
import { TextAnimationSlideUp, TextAnimationDeZoom } from 'react-native-text-effects';
import * as Animatable from 'react-native-animatable';
import { Colors } from './constants';
var arr = [{ image: require('./assets/rock.png') }, { image: require('./assets/paper.png') }, { image: require('./assets/scissors.png') }];
var arr2 = [{ image: require('./assets/rock2.png') }, { image: require('./assets/paper2.png') }, { image: require('./assets/scissors2.png') }];
var win_case = [['rock', 'scissor'], ['scissor', 'paper'], ['paper', 'rock']];
var SELECTIONS = [
{
name: 'rock',
beats: 'scissors',
rank: 0
},
{
name: 'paper',
beats: 'rock',
rank: 1
},
{
name: 'scissors',
beats: 'paper',
rank: 2
}
]
function isWinner(selection, opponentSelection) {
return selection.beats === opponentSelection.name
}
function randomSelection() {
const randomIndex = Math.floor(Math.random() * SELECTIONS.length)
return SELECTIONS[randomIndex]
}
export default class App extends React.Component {
state = {
selected_uri: './assets/rock.png',
uri: require('./assets/rock.png'),
player1choose: 0,
player2choose: 0,
player1message: "-",
player2message: "-",
};
render() {
return (
<View>
<View >
<TouchableOpacity
onPress={() => {
const player1choice = randomSelection();
const player2choice = randomSelection();
const player1win = isWinner(player1choice, player2choice);
const player2win = isWinner(player2choice, player1choice);
if (player1win) { this.setState({ player1message: "Win", player2message: "Lose" });}
else if (player2win) {this.setState({ player1message: "Lose", player2message: "Win" });}
else {this.setState({ player1message: "Draw", player2message: "Draw" });}
this.setState({ player1choose: player1choice.rank, player2choose: player2choice.rank })
}}>
<View >
<Image source={require('./assets/playicon.png')} />
</View>
<View >
<Text>{this.state.player1message} </Text>
</View>
</TouchableOpacity>
</View>
<TextAnimationSlideUp value={this.state.player2message} delay={100} duration={1000} style={{ transform: [{ rotateX: "180deg" }, { rotateY: '180deg' }], color: 'purple', fontSize: 40 }} />
<TextAnimationSlideUp value={this.state.player1message} delay={100} duration={1000} style={{ color: 'yellow', fontSize: 40 }} />
<Animatable.Text animation="zoomInUp">
<Text>{this.state.player1message} </Text>
</Animatable.Text>
<View >
<Animatable.Image source={arr[this.state.player1choose].image} animation="zoomInUp">
</Animatable.Image>
</View>
</View>
); }}
Can anybody help me with this

Related

ReactNative FlatList not rendering

I am new to ReactNative programming and .tsx files in general. I'm trying to display a basic FlatList and have copied the below code from the ReactNative docs here: (https://reactnative.dev/docs/flatlist). It's only slightly modified to fit into my ReactNative app which I am editing in Visual Studio code.
Does anyone know the correct way to display a FlatList? I've spent 2-3 days tinkering with this but I'm obviously missing some crucial ingredient. Beats me.
import * as React from "react";
import { useState, Component } from "react";
import EditScreenInfo from "../components/EditScreenInfo";
import { StyleSheet, Text, View, Dimensions, TouchableOpacity, Alert, FlatList, SafeAreaView, StatusBar } from "react-native";
// import PaymentScreen from "./PaymentScreen";
import { Driver } from "../models/Driver";
// tslint:disable-next-line:typedef
const styles = StyleSheet.create({
page: {
flex: 1,
justifyContent: "center",
alignItems: "center",
backgroundColor: "#FFF"
},
container: {
height: 750,
width: 750,
backgroundColor: "tomato"
},
map: {
flex: 1,
height:750,
width:750
},
item: {
padding: 10,
fontSize: 18,
height: 44,
},
title: {
fontSize: 18
}
});
// tslint:disable-next-line: typedef
const DATA = [
{
id: "bd7acbea-c1b1-46c2-aed5-3ad53abb28ba",
title: "First Item",
},
{
id: "3ac68afc-c605-48d3-a4f8-fbd91aa97f63",
title: "Second Item",
},
{
id: "58694a0f-3da1-471f-bd96-145571e29d72",
title: "Third Item",
},
];
// tslint:disable-next-line:typedef
const Item = ({ item, onPress, backgroundColor, textColor }: {
item: any;
onPress: any;
backgroundColor: any;
textColor: any;
}) => (
<TouchableOpacity onPress={onPress} style={[styles.item, backgroundColor]}>
<Text style={[styles.title, textColor]}>{item.title}</Text>
</TouchableOpacity>
);
export default class TabFourScreen extends Component {
drivers: Driver[] = []; // fetch these from backend... for now you can STUB
selectedId: any = useState(null);
setSelectedId: any = useState(null);
renderItem: any = ({ item }: {item: any}) => {
// tslint:disable-next-line:typedef
const backgroundColor = item.id === this.selectedId ? "#6e3b6e" : "#f9c2ff";
// tslint:disable-next-line:typedef
const color = item.id === this.selectedId ? "white" : "black";
return (
<Item
item={item}
onPress={() => this.setSelectedId(item.id)}
backgroundColor={{ backgroundColor }}
textColor={{ color }}
/>
);
}
render = () => {
return (
<View style={styles.page}>
<SafeAreaView style={styles.container}>
<FlatList
data={DATA}
renderItem={this.renderItem}
keyExtractor={(item) => item.id}
extraData={this.selectedId}
/>
</SafeAreaView>
</View>
);
}
}
First of all you can't use hooks like useState in a Class Component, you have to use Function Component: https://reactnative.dev/docs/getting-started#function-components-and-class-components.
Secondly, you have set width: 750 to your SafeAreaView's style, so the text doesn't appear on the screen you see but appears before.
Try this code:
import * as React from 'react';
import { useState, Component } from 'react';
import {
StyleSheet, Text, View, Dimensions, TouchableOpacity, Alert, FlatList, SafeAreaView, StatusBar,
} from 'react-native';
// import PaymentScreen from "./PaymentScreen";
// tslint:disable-next-line:typedef
const styles = StyleSheet.create({
page: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#FFF',
},
container: {
height: 750,
width: '100%',
backgroundColor: 'tomato',
},
map: {
flex: 1,
height: 750,
width: 750,
},
item: {
height: 44,
},
title: {
fontSize: 25,
color: 'white',
},
});
// tslint:disable-next-line: typedef
const DATA = [
{
id: 'bd7acbea-c1b1-46c2-aed5-3ad53abb28ba',
title: 'First Item',
},
{
id: '3ac68afc-c605-48d3-a4f8-fbd91aa97f63',
title: 'Second Item',
},
{
id: '58694a0f-3da1-471f-bd96-145571e29d72',
title: 'Third Item',
},
];
// tslint:disable-next-line:typedef
const Item = ({
item, onPress, backgroundColor, textColor,
}) => (
<TouchableOpacity onPress={onPress} style={[styles.item, backgroundColor]}>
<Text style={[styles.title, textColor]}>{item.title}</Text>
</TouchableOpacity>
);
const TabFourScreen = () => {
const [selectedId, setSelectedId] = useState(null);
const renderItem = ({ item }) => {
// tslint:disable-next-line:typedef
const backgroundColor = item.id === selectedId ? '#6e3b6e' : '#f9c2ff';
// tslint:disable-next-line:typedef
const color = item.id === selectedId ? 'white' : 'black';
return (
<Item
item={item}
key={item.id}
onPress={() => setSelectedId(item.id)}
backgroundColor={{ backgroundColor }}
textColor={{ color }}
/>
);
};
return (
<View style={styles.page}>
<SafeAreaView style={styles.container}>
<FlatList
data={DATA}
renderItem={renderItem}
keyExtractor={(item) => item.id}
extraData={selectedId}
/>
</SafeAreaView>
</View>
);
};
export default TabFourScreen;
I removed typescript just to test, feel free to add it again.
don't use this.renderItem use only renderItem

How to display list of countries as webpage in expo react native

I am beginner with react native expo, just creating my first project. I am able to make a flat list and app is working great so far.
However now I need to make something like this,
As being newbie, I am not sure where to start, It seems like a webview is used but I am not sure how to put flatview into webview, or am I completely on wrong track ?
This is what I coded so far,
import React from 'react';
import { SafeAreaView, View, FlatList, StyleSheet, Text, StatusBar } from 'react-native';
const DATA = [
{
id: 'bd7acbea-c1b1-46c2-aed5-3ad53abb28ba',
title: 'First Item',
},
{
id: '3ac68afc-c605-48d3-a4f8-fbd91aa97f63',
title: 'Second Item',
},
{
id: '58694a0f-3da1-471f-bd96-145571e29d72',
title: 'Third Item',
},
];
const Item = ({ title }) => (
<View style={styles.item}>
<Text style={styles.title}>{title}</Text>
</View>
);
const App = () => {
const renderItem = ({ item }) => (
<Item title={item.title} />
);
return (
<SafeAreaView style={styles.container}>
<FlatList
data={DATA}
renderItem={renderItem}
keyExtractor={item => item.id}
/>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
marginTop: StatusBar.currentHeight || 0,
},
item: {
backgroundColor: '#f9c2ff',
padding: 20,
marginVertical: 8,
marginHorizontal: 16,
},
title: {
fontSize: 32,
},
});
export default App;
Result:
Code:
import React from "react";
import { FlatList, SafeAreaView, StyleSheet, Text, View } from "react-native";
class App extends React.Component {
state = {
data: [
{ id: "00", name: "Mazda RX-7" },
{ id: "01", name: "McLaren F1" },
{ id: "02", name: "Mini Cooper" },
{ id: "03", name: "BMW 645 Ci" }
]
};
render() {
const columns = 3;
return (
<SafeAreaView>
<FlatList
data={createRows(this.state.data, columns)}
keyExtractor={item => item.id}
numColumns={columns}
renderItem={({ item }) => {
if (item.empty) {
return <View style={[styles.item, styles.itemEmpty]} />;
}
return (
<View style={styles.item}>
<Text style={styles.text}>{item.name}</Text>
</View>
);
}}
/>
</SafeAreaView>
);
}
}
function createRows(data, columns) {
const rows = Math.floor(data.length / columns);
let lastRowElements = data.length - rows * columns;
while (lastRowElements !== columns) {
data.push({
id: `empty-${lastRowElements}`,
name: `empty-${lastRowElements}`,
empty: true
});
lastRowElements += 1;
}
return data;
}
const styles = StyleSheet.create({
item: {
alignItems: "center",
backgroundColor: "#dcda48",
flexBasis: 0,
flexGrow: 1,
margin: 4,
padding: 20
},
itemEmpty: {
backgroundColor: "transparent"
},
text: {
color: "#333333"
}
});
export default App;

How to show 2 items in one pagination of react native snap carousel

How to dispaly 2 items for one pagination(first dot) and if we swipe then next 2 items should display with showing second dot active.
And if it is odd then last item should display my own component in react native snap carousel.
I would suggest that you go ahead and make the item you're rendering in the Carousel one that renders 2 things at once. The Carousel will paginate on whatever you pass to it, so if you're passing something with 2 items in it, it'll paginate on that, so for example:
<Carousel
layout="default"
data={arr}
renderItem={
({ item, index }) => (
<View style={styles.imageWrapper}>
<Image
style={styles.image}
source={item[0]}
resizeMode="cover"
accessibilityLabel="thumbnail"
/>
<Image
style={styles.image}
source={item[1]}
resizeMode="cover"
accessibilityLabel="thumbnail"
/>
</View>
)
}
lockScrollWhileSnapping={true} // Prevent the user from swiping again while the carousel is snapping to a position.
sliderWidth={screenWidth}
sliderHeight={screenWidth * 0.5}
itemWidth={screenWidth - 40}
activeSlideOffset={50}
enableSnap
onSnapToItem={onSnapToItem}
removeClippedSubviews={false}
firstItem={0}
contentContainerCustomStyle={styles.style}
/>
Create a function that split "entries" array into smaller arrays based on the size that you want
var slides = [];
const entriesSplitter = () => {
let size = 2; //Based on the size you want
while (entries.length > 0) {
slides.push(entries.splice(0, size));
}
};
then pass the slides array to <Carousel data={slides}/> then render each slide
in _renderItem
consider the following example:-
import React, { useState, useRef } from "react";
import { View,Text, Dimensions } from "react-native";
import Carousel, { Pagination } from "react-native-snap-carousel";
const { width: screenWidth, height: screenHeight } = Dimensions.get("window");
const myCarousel = () => {
const [activeSlide, setActiveSlide] = useState(0);
const carousel = useRef();
const entries = [
{
title: "Adidas"
},
{
title: "Nike"
},
{
title: "Puma"
},
{
title: "Reebok"
}
];
var slides = [];
const entriesSplitter = () => {
let size = 2; //Based on the size you want
while (entries.length > 0) {
slides.push(entries.splice(0, size));
}
};
// render every single slide
const _renderItem = ({ item,index }) => {
return (
<View style={{ flexDirection: "row", flexWrap: "wrap" }}>
{item.map(item => {
return <Text key={index}>{item.title}</Text>;
})}
</View>
);
};
return (
<View>
{entriesSplitter()}
<Carousel
ref={carousel}
data={slides}
renderItem={_renderItem}
onSnapToItem={index => setActiveSlide(index)}
sliderWidth={screenWidth}
sliderHeight={screenHeight}
itemWidth={screenWidth}
/>
<Pagination
dotsLength={2} // also based on number of sildes you want
activeDotIndex={activeSlide}
containerStyle={{ backgroundColor: "red", borderWidth: 2 }}
dotStyle={{
width: 10,
height: 10,
borderRadius: 5,
marginHorizontal: 8,
backgroundColor: "black"
}}
inactiveDotStyle={{
backgroundColor: "pink"
}}
inactiveDotOpacity={0.4}
inactiveDotScale={0.6}
/>
</View>
);
};
export default myCarousel;
This is how I implemented to show 3 carousels. We can customize it in many ways
import React from "react";
import { View, Dimensions, StyleSheet, Image } from "react-native";
import Carousel from "react-native-snap-carousel";
const windowWidth = Dimensions.get("window").width;
export default function MyCarousel() {
const images = [
{ id: 1, image: require("../assets/home-slider-1.jpg") },
{ id: 2, image: require("../assets/home-slider-2.jpg") },
{ id: 3, image: require("../assets/home-slider-3.jpg") },
{ id: 4, image: require("../assets/home-slider-4.jpg") }
];
// const imagesUri = [
// { id: 1, image: { uri: 'https://i.imgur.com/gG5Egof.jpg' } },
// { id: 2, image: { uri: 'https://i.imgur.com/gG5Egof.jpg' } },
// { id: 3, image: { uri: 'https://i.imgur.com/gG5Egof.jpg' } },
// { id: 4, image: { uri: 'https://i.imgur.com/gG5Egof.jpg' } }
// ];
const _renderItem = ({ item }) => {
return (
<View style={styles.slide}>
<Image
source={item.image}
style={styles.image}
// resizeMode="center"
></Image>
</View>
);
};
return (
<View style={styles.wrapper}>
<Carousel
data={images}
renderItem={_renderItem}
sliderWidth={windowWidth}
itemWidth={windowWidth - 70}
enableMomentum={false}
lockScrollWhileSnapping
autoplay
useScrollView
loop
autoplayInterval={3000}
/>
</View>
);
}
const styles = StyleSheet.create({
wrapper: {
height: 150
},
slide: {
flex: 1,
justifyContent: "center",
alignItems: "center",
backgroundColor: "#fff"
},
image: {
flex: 1,
height: "100%",
width: "100%",
alignItems: "center",
justifyContent: "center"
}
});

React Native Search Dropdown

I'm working on React native app. I'm looking for a searchable dropdown which I need to implement in many places.
Below see below video for reference:
Sample Video
I have implemented below third parties but they are not same as I need:
https://www.npmjs.com/package/react-native-searchable-dropdown
https://www.npmjs.com/package/react-native-searchable-selectbox
https://github.com/toystars/react-native-multiple-select
I tried implementing something similar a while ago and at the time I dropped the idea of having a drop down as it was inconsistent on both platforms & I could not find a perfect solution. I cannot see your video but I think I know where you're going with this.
Here is my advice:
I would create a separate screen that opens on the tap on this component that would be a 'dropdown', and in there create a searchable/filtrable list. You could try doing that using this: https://www.npmjs.com/package/searchable-flatlist, or create your own flatlist, which is super easy and allows for more customization!
EDIT:
If you don't want a separate screen use this: https://www.npmjs.com/package/react-native-searchable-dropdown
try implementing one :
const sports = ["Badminton","Cricket","Chess","Kho-Kho","Kabbadi","Hockey","Boxing","Football","Basketball","Volleyball","Tennis","Table Tennis"];
predict(){
let q = this.state.query;
let arr = sports.filter(ele => ele.toLowerCase().indexOf(q.toLowerCase()) != -1).splice(0,5);
this.setState((prev = this.state)=>{
let obj={};
Object.assign(obj,prev);
obj.predictions.splice(0,obj.predictions.length);
arr.forEach(ele=>{
obj.predictions.push({key : ele});
});
return obj;
});
}
<TouchableWithoutFeedback onPress={()=>{this.setState({done : true})}}>
<ScrollView
keyboardShouldPersistTaps='handled'
contentContainerStyle={style.content}
>
<View>
<TextInput
onChangeText={(text)=>{
this.setState({query : text , done : false});
this.predict();
}}
placeholder="What do you want to play ?"
placeholderTextColor="#A6A4A4"
value = {this.state.query}
onSubmitEditing = {()=>{this.setState({done : true})}}
underlineColorAndroid = "#0098fd"
></TextInput>
<TouchableOpacity onPress={()=>{this.filteredEvents()}}><Icon name="search" color = "#0098fd" size = {20}></Icon></TouchableOpacity>
</View>
{
this.state.predictions.length != 0 && !this.state.done &&
<FlatList
style={styles.predictor_view}
data={this.state.predictions}
extraData = {this.state}
renderItem = {
({item})=>(
<TouchableOpacity
style={styles.predictions}
onPress={()=>{
console.log('ok');
this.setState({query : item.key,done : true});
console.log(this.state);
}}>
<Text>{item.key}</Text>
</TouchableOpacity>
)
}
/>
}
</ScrollView>
</TouchableWithoutFeedback>
I have used react-native-autocomplete-input
I have written a component to help in the dropdown:
customDropDownComponent.js
/*This is an example of AutoComplete Input/ AutoSuggestion Input*/
import React, { Component } from 'react';
import { StyleSheet, Text, TouchableOpacity, View, Button, ScrollView } from 'react-native';
//import all the components we are going to use.
import Autocomplete from 'react-native-autocomplete-input'
//import Autocomplete component
class CustomDropDownComponent extends Component {
constructor(props) {
super(props);
//Initialization of state
//films will contain the array of suggestion
//query will have the input from the autocomplete input
this.state = {
query: '',
data: [],
dataDuplicate:[],
itemSelected: false
};
}
componentDidMount() {
//Loading all data
this.loadData()
}
findElement(query, text, itemSelected) {
//method called everytime when we change the value of the inputquery === '' ||
if (itemSelected === true||query==='') {
//if the query is null or an item is selected then return blank
return [];
}
//making a case insensitive regular expression to get similar value from the data json
const regex = new RegExp(`${query.trim()}`, 'i');
//return the filtered data array according the query from the input
var newList = [];
var result = this.state.IATADup.filter(data => {
if (data.id.search(regex) === 0) {
newList.push(data);
return false;
} else {
return data.id.search(regex) >= 0;
}
});
result = newList.concat(result);
this.props.adjustMargin(1, result.length);//expadnding space in page to make room for dropdown
this.setState({ data: result, query: text, itemSelected: itemSelected });
}
loadData = () => {
var dataToLoad = Commondata.aircraftDetail
dataToLoad.sort(function (a, b) {
if (a.id > b.id) {
return 1;
}
if (b.id > a.id) {
return -1;
}
return 0;
});
this.setState({
dataDuplicate: dataToLoad
})
}
render() {
const { query } = this.state;
const data = this.state.data;
const comp = (a, b) => a.toLowerCase().trim() === b.toLowerCase().trim();
var inputContainerStyle = styles.inputContainerStyle;
if (this.props.destinationBorder === "#FF0000") {
inputContainerStyle = styles.inputContainerRedStyle;
}
return (
<View style={styles.container} >
<Autocomplete
autoCapitalize="none"
autoCorrect={false}
flatListProps={{ nestedScrollEnabled: true }}
containerStyle={styles.autocompleteContainer}
listStyle={styles.listStyle}
inputContainerStyle={inputContainerStyle}
data={data}
keyExtractor={(item, i) => { return i }
defaultValue={query}
onChangeText={text => {
//handle input
if (text.trim() === "") this.props.adjustMarginBack();//adjust margin to normal in case of empty searrch element
this.findElement(text, text, false);//search for element
}}
placeholder={en.pick_one}
renderItem={({ item }) => (
//you can change the view you want to show in suggestion from here
<TouchableOpacity onPress={() => {
this.props.adjustMarginBack()
this.setState({ query: item.id, itemSelected: true, data: [] });
}}>
<Text style={styles.itemText}>
{item.id}
</Text>
<Text style={styles.itemSubText}>
{item.name}
</Text>
</TouchableOpacity>
)}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
backgroundColor: '#F5FCFF'
},
autocompleteContainer: {
backgroundColor: '#ffffff',
borderWidth: 0,
},
inputContainerStyle: {
borderWidth: 0.5, borderColor: '#D9D9D9', padding: '1.5%'
},
inputContainerRedStyle: {
borderWidth: 0.5, borderColor: '#FF0000', padding: '1.5%'
},
descriptionContainer: {
flex: 1,
justifyContent: 'center',
padding: '5%'
},
itemText: {
fontSize: 15,
paddingTop: 5,
paddingBottom: 5,
margin: 2,
},
itemSubText: {
fontSize: 10,
paddingTop: 5,
paddingBottom: 5,
margin: 2,
marginLeft: 10
},
infoText: {
textAlign: 'center',
fontSize: 16,
},
listStyle: {
height: 100,
position: "relative",
zIndex: 999
}
});
export default CustomComponent;
Now in the display screen:
app.js
import React, { Component } from 'react';
import { View, Text, ScrollView } from 'react-native';
import CustomDropDownComponent from './CustomDropDownComponent.js'
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
};
}
render() {
return (
<View>
<ScrollView
nestedScrollEnabled={true}
keyboardShouldPersistTaps={'handled'}>
<CustomDropDownComponent /*Handle all inputs and margin resets as props *//>
</ScrollView>
</View>
);
}
}

Hot to get selected value from another component?

I create a component Confirm.js with react-native <Modal /> that has two DropDownMenu and two <Button />.
I want user click the Yes <Button /> than i can get the DropDownMenu onOptionSelected value. I think i should use this.props but i have no idea how to do it.
I want get the value in MainActivity.js from Confirm.js
Any suggestion would be appreciated. Thanks in advance.
Here is my MainActivty.js click the <Button /> show <Confirm />:
import React, { Component } from 'react';
import { Confirm } from './common';
import { Button } from 'react-native-elements';
class MainActivity extends Component {
constructor(props) {
super(props);
this.state = { movies: [], content: 0, showModal: false, isReady: false };
}
// close the Confirm
onDecline() {
this.setState({ showModal: false });
}
render() {
return (
<View style={{ flex: 1 }}>
<Button
onPress={() => this.setState({ showModal: !this.state.showModal })}
backgroundColor={'#81A3A7'}
containerViewStyle={{ width: '100%', marginLeft: 0 }}
icon={{ name: 'search', type: 'font-awesome' }}
title='Open the confirm'
/>
<Confirm
visible={this.state.showModal}
onDecline={this.onDecline.bind(this)}
>
</Confirm>
</View>
);
}
}
export default MainActivity;
Confirm.js:
import React from 'react';
import { Text, View, Modal } from 'react-native';
import { DropDownMenu } from '#shoutem/ui';
import TestConfirm from './TestConfirm';
import { CardSection } from './CardSection';
import { Button } from './Button';
import { ConfirmButton } from './ConfirmButton';
const Confirm = ({ children, visible, onAccept, onDecline }) => {
const { containerStyle, textStyle, cardSectionStyle } = styles;
return (
<Modal
visible={visible}
transparent
animationType="slide"
onRequestClose={() => {}}
>
<View style={containerStyle}>
<CardSection style={cardSectionStyle}>
{/* Here is my DropDownMenu */}
<TestConfirm />
</CardSection>
<CardSection>
<ConfirmButton onPress={onAccept}>Yes</ConfirmButton>
<ConfirmButton onPress={onDecline}>No</ConfirmButton>
</CardSection>
</View>
</Modal>
);
};
const styles = {
cardSectionStyle: {
justifyContent: 'center'
},
textStyle: {
flex: 1,
fontSize: 18,
textAlign: 'center',
lineHeight: 40
},
containerStyle: {
backgroundColor: 'rgba(0, 0, 0, 0.75)',
position: 'relative',
flex: 1,
justifyContent: 'center'
},
buttonStyle: {
flex: 1,
alignSelf: 'stretch',
backgroundColor: '#fff',
borderRadius: 5,
borderWidth: 1,
borderColor: '#007aff',
marginLeft: 5,
marginRight: 5
}
};
export { Confirm };
TestConfirm.js
import React, { Component } from 'react';
import { View } from 'react-native';
import { DropDownMenu, Title, Image, Text, Screen, NavigationBar } from '#shoutem/ui';
import {
northCities,
centralCities,
southCities,
eastCities,
islandCities
} from './CityArray';
class TestConfirm extends Component {
constructor(props) {
super(props);
this.state = {
zone: [
{
id: 0,
brand: "North",
children: northCities
},
{
id: 1,
brand: "Central",
children: centralCities
},
{
id: 2,
brand: "South",
children: southCities
},
{
id: 3,
brand: "East",
children: eastCities
},
{
id: 4,
brand: "Island",
children: islandCities
},
],
}
}
render() {
const { zone, selectedZone, selectedCity } = this.state
return (
<Screen>
<DropDownMenu
style={{
selectedOption: {
marginBottom: -5
}
}}
styleName="horizontal"
options={zone}
selectedOption={selectedZone || zone[0]}
onOptionSelected={(zone) =>
this.setState({ selectedZone: zone, selectedCity: zone.children[0] })}
titleProperty="brand"
valueProperty="cars.model"
/>
<DropDownMenu
style={{
selectedOption: {
marginBottom: -5
}
}}
styleName="horizontal"
options={selectedZone ? selectedZone.children : zone[0].children} // check if zone selected or set the defaul zone children
selectedOption={selectedCity || zone[0].children[0]} // set the selected city or default zone city children
onOptionSelected={(city) => this.setState({ selectedCity: city })} // set the city on change
titleProperty="cnCity"
valueProperty="cars.model"
/>
</Screen>
);
}
}
export default TestConfirm;
If i console.log DropDownMenu onOptionSelected value like the city it would be
{cnCity: "宜蘭", enCity: "Ilan", id: 6}
I want to get the enCity from MainActivity.js
ConfirmButton.js:
import React from 'react';
import { Text, TouchableOpacity } from 'react-native';
const ConfirmButton = ({ onPress, children }) => {
const { buttonStyle, textStyle } = styles;
return (
<TouchableOpacity onPress={onPress} style={buttonStyle}>
<Text style={textStyle}>
{children}
</Text>
</TouchableOpacity>
);
};
const styles = {
{ ... }
};
export { ConfirmButton };
You can pass a function to related component via props and run that function with the required argument you got from the dropdowns. Because you have couple of components in a tree it is going to be a little hard to follow but if you get the idea I'm sure you'll make it simpler. Also after getting comfortable with this sort of behavior and react style coding you can upgrade your project to some sort of global state management like redux, flux or mobx.
Sample (removed unrelated parts)
class MainActivity extends Component {
onChangeValues = (values) => {
// do some stuf with the values
// value going to have 2 properties
// { type: string, value: object }
const { type, value } = values;
if(type === 'zone') {
// do something with the zone object
} else if(type === 'city') {
// do something with the city object
}
}
render() {
return(
<Confirm onChangeValues={this.onChangeValues} />
)
}
}
const Confirm = ({ children, visible, onAccept, onDecline, onChangeValues }) => {
return(
<TestConfirm onChangeValues={onChangeValues} />
)
}
class TestConfirm extends Component {
render() {
return(
<Screen>
<DropDownMenu
onOptionSelected={(zone) => {
// run passed prop with the value
this.props.onChangeValues({type: 'zone', value: zone});
this.setState({ selectedZone: zone, selectedCity: zone.children[0] });
}}
/>
<DropDownMenu
onOptionSelected={(city) => {
// run passed prop with the value
this.props.onChangeValues({type: 'city', value: city});
this.setState({ selectedCity: city })
}}
/>
</Screen>
)
}
}