How to multiselect items in flatlist react native - react-native

How to multi select and highlight the components in a react native flatlist. I have checked the doc. But it is bit confusing can anybody help me. I have done single select using this method.Could any one modify this to a multi select.I will give the snack link here where i have done the single select
import * as React from 'react';
import {
Text,
View,
StyleSheet,
FlatList,
TouchableOpacity,
} from 'react-native';
import Constants from 'expo-constants';
const Data = [
{
id: 1,
first_name: 'Sile',
},
{
id: 2,
first_name: 'Clementia',
},
{
id: 3,
first_name: 'Brita',
},
{
id: 4,
first_name: 'Duke',
},
{
id: 5,
first_name: 'Hedvig',
},
{
id: 6,
first_name: 'Paulie',
},
{
id: 7,
first_name: 'Munmro',
},
{
id: 8,
first_name: 'Dyanna',
},
{
id: 9,
first_name: 'Shanta',
},
{
id: 10,
first_name: 'Bambi',
},
];
// or any pure javascript modules available in npm
import { Card } from 'react-native-paper';
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {
selectedItem: null,
};
}
onPressHandler(id) {
this.setState({ selectedItem: id });
}
render() {
return (
<View>
<FlatList
extraData={this.state.selectedItem} //Must implemented
//horizontal={true}
data={Data}
keyExtractor={item => item.id.toString()}
showsHorizontalScrollIndicator={false}
renderItem={({ item }) => (
<TouchableOpacity onPress={() => this.onPressHandler(item.id)}>
<Card
style={
this.state.selectedItem === item.id
? {
padding: 10,
borderRadius: 5,
backgroundColor: '#000000',
}
: {
padding: 10,
borderRadius: 5,
backgroundColor: '#a1a1a1',
}
}>
<Text>{item.first_name}</Text>
</Card>
</TouchableOpacity>
)}
/>
</View>
);
}
}
const styles = StyleSheet.create({
});
this is the sample data

I have made some changes and made your flatlist as multiselect. Please visit this link.
I have made below changes for making this as multiselect:
Added dummy data in state & passed it to flatlist's data.
On item press iterate data and for corresponding item set item.selected=true.
Inside flatlist's renderItem if item.selected==true then show selection else remove selection.
Please check and let me know.

check this logic,
...
this.state = {
clientsArray: clientsArray,
selectedClients: []
};
//'clientsArray' is your data array
...
_renderCell = ({ item, index }) => {
const { selectedClients, clientsArray } = this.state;
let isSelected =
selectedClients.filter(o => {
return o.id === item.id;
}).length > 0
? true
: false;
//change your UI based on the 'isSelected' value
return (
<TouchableOpacity
activeOpacity={Constants.ACTIVE_OPACITY}
onPress={() => {
this._didSelectClient(item);
}}
>
{
//Your component
}
</TouchableOpacity>
}
_didSelectClient = selectedItem => {
let selectedClients = this.state.selectedClients;
let isItemSelected =
selectedClients.filter(item => {
return item.id.includes(selectedItem.id);
}).length > 0
? true
: false;
if (isItemSelected) {
const index = selectedClients.findIndex(
obj => obj.id === selectedItem.id
);
selectedClients.splice(index, 1);
} else {
selectedClients.push(selectedItem);
}
this.setState({ selectedClients });
};
render() {
...
<FlatList
style={{ flex: 1 }}
data={clientsArray}
renderItem={this._renderCell}
keyExtractor={(item, index) => index.toString()}
extraData={this.props}
ListEmptyComponent={this._renderEmptyComponent}
/>
...
}

Related

How to remove this error: Error: The component for route 'Home' must be a React component

I am trying to make a searchable dropdown in react native as in this website https://www.npmjs.com/package/react-native-searchable-dropdown. They have made it in App.js while I have made it in FriendRequests.js. I have installed by doing npm install --save react-native-searchable-dropdown.
After doing npm start I am getting this error in red background:
Is it a problem in Home.js or FriendRequests.js. This is my FriendRequests.js file:
import React, { Fragment, Component } from 'react';
import SearchableDropdown from 'react-native-searchable-dropdown';
var items = [
{
id: 1,
name: 'JavaScript',
},
{
id: 2,
name: 'Java',
},
...
{
id: 7,
name: 'Go',
},
{
id: 8,
name: 'Swift',
},
];
class FriendRequests extends React.Component {
constructor(props) {
super(props);
this.state = {
selectedItems: [
{
id: 7,
name: 'Go',
},
{
id: 8,
name: 'Swift',
}
]
}
}
render() {
return (
<Fragment>
<SearchableDropdown
onItemSelect={(item) => {
const items = this.state.selectedItems;
items.push(item)
this.setState({ selectedItems: items });
}}
onRemoveItem={(item, index) => {
const items = this.state.selectedItems.filter((sitem) => sitem.id !== item.id);
this.setState({ selectedItems: items });
}}
items={items}
defaultIndex={2}
resetValue={false}
textInputProps={
{
placeholder: "placeholder",
underlineColorAndroid: "transparent",
onTextChange: text => alert(text)
}
}
listProps={
{
nestedScrollEnabled: true,
}
}
/>
</Fragment>
)
}
}
Can anyone help me in fixing this error.
This is my Home component:
import React, { useState, useEffect, useReducer } from 'react';
import { useAuth } from "#providers/AuthProvider";
import { Block, Button } from "galio-framework";
import { StyleSheet, Dimensions, FlatList, View, Animated } from 'react-native';
import * as theme from '#utils/theme';
import { NewPostCard } from '#components/Post/NewPostCard';
import { Post } from '#components/Post/Post';
import { useApi } from '#providers/ApiProvider';
const { width } = Dimensions.get('window');
import update from 'immutability-helper';
import { NavigationEvents } from 'react-navigation';
function initState ( ) {
return {
page: 1,
posts: []
}
}
function postReducer ( state, action ) {
switch( action.type ) {
case 'set-posts': {
state = {
posts: action.payload.data,
page: action.payload.page
}
return state;
}
case 'update-post': {
const index = state.posts.findIndex( x => x.id === action.payload.id
);
if ( index > -1 ) {
const oldPost = state.posts[index];
const newPost = { ...oldPost, ...action.payload };
state = {
posts: update( state.posts, {
$splice: [[ index, 1, newPost ]]
} ),
page: action.payload.page
}
}
return state;
}
case 'add-posts': {
state = {
posts: update(state.posts, { $push: action.payload.data } ),
page: action.payload.page
}
return state;
}
case 'reset': {
return initState( action.payload );
}
default:
return state;
}
}
export function HomeScreen() {
const { fetch } = useAuth();
const { get, post: apiPost } = useApi();
const [isLoading, setIsLoading] = useState(true);
const [ state, dispatch ] = useReducer( postReducer, { page: 1, posts: [] }, initState );
const [showNewPostCard, setShowNewPostCard ] = useState( false );
function fetchPosts ( page ) {
setIsLoading( true );
if ( !page ) {
dispatch({ type: 'reset' })
}
get('/posts', {
params: {
page: page || 1,
limit: 15
}
})
.then( data => {
setIsLoading( false );
if ( page && page > state.page ) {
dispatch({ type: 'add-posts', payload: { ...data, page } })
} else {
dispatch({ type: 'set-posts', payload: data })
}
} )
}
function likePost ( post ) {
apiPost(`/posts/${post.id}/likes`)
.then( res => {
return get(`/posts/${post.id}`)
} )
.then( ( data ) => {
dispatch({ type: 'update-post', payload: data })
} )
}
function commentPost ( content, post ) {
apiPost(`/posts/${post.id}/comments`, {
content
})
.then( ( data ) => {
return get(`/posts/${post.id}`)
} )
.then( ( data ) => {
dispatch({ type: 'update-post', payload: data })
} )
}
useEffect(() => {
fetch();
}, []);
return (
<Block flex style={{ paddingHorizontal: theme.SIZES.BASE * 0.5 }}>
<NavigationEvents
onWillFocus={ ( ) => fetchPosts() }
></NavigationEvents>
<FlatList
ItemSeparatorComponent={ () =>
<Block style={{paddingHorizontal: theme.SIZES.BASE * 0.5}}>
<View style={[styles.separator]} />
</Block>
}
ListHeaderComponent={ ( ) => {
return (
<Block style={{padding: theme.SIZES.BASE * 0.5 }}>
<NewPostCard></NewPostCard>
</Block>
)
} }
initialNumToRender={3}
style={styles.postlist}
data={state.posts}
onRefresh={fetchPosts}
onEndReached={ ( num ) => fetchPosts( state.page++ )}
onEndReachedThreshold={ 0.5 }
refreshing={isLoading}
keyExtractor={item => item.id}
renderItem={({item, index, separators}) => (
<Block style={{padding: theme.SIZES.BASE * 0.5 }}>
<Post item={item}
onPostLike={ ( post ) => {
likePost( post )
} }
onCommentPost={ ( comment, post ) => {
commentPost(comment, post);
}}></Post>
</Block>
)}>
</FlatList>
</Block>
);
}
const styles = StyleSheet.create({
separator: {
borderBottomWidth: StyleSheet.hairlineWidth,
borderColor: 'rgba(0,0,0,.2)',
marginVertical: theme.SIZES.BASE * 0.5
},
postlist: {
marginTop: theme.SIZES.BASE,
marginHorizontal: -(theme.SIZES.BASE * 0.5),
height: 100,
minHeight: 100
},
divider: {
borderRightWidth: 0.3,
borderRightColor: theme.COLORS.ICON,
},
tab: {
backgroundColor: theme.COLORS.TRANSPARENT,
width: width * 0.5,
paddingVertical: 20,
borderRadius: 0,
borderWidth: 0,
height: 24,
elevation: 0,
},
options: {
marginBottom: 30,
marginTop: 20,
elevation: 4,
},
tabTitle: {
lineHeight: 19,
fontWeight: '400',
color: theme.COLORS.SECONDARY
},
})
Change your home function declaration
from
export function HomeScreen() {
...
export const HomeScreen = props => {
...
because you can only use hooks inside a functional component and react-navigation allows only only react components not functions

Is there a way to display the content of an array

I would like to display the content "product_id" from
the "products" array
I'm setting up a new component to view the product_id from the
products array.
Here the expectation is to display the contents of the array.
import { View, Text } from 'react-native'
import { Button, SpinnerButton } from '../../components'
import { inject, observer } from 'mobx-react/native'
import styles from './style'
import { calcSize } from '../../utils'
#inject('UserStore')
#observer
class ProductInfo extends Component {
constructor(props) {
super(props)
// this.state = {}
// this.item = this.props.navigation.state.item ? this.props.navigation.state.params.item : 'no item'
}
render() {
return (
<View style={styles.container}>
{this.props.navigation.state.params.item.products.map(pr => (
<Text>{pr.product_id}</Text>
))}
</View>
)
}
}
export default ProductInfo
here i send the param with the "ProductInfo" to the page above..
import { View, Text, FlatList, TouchableOpacity } from 'react-native'
import Style from './style'
import { inject, observer } from 'mobx-react/native'
import Icon from 'react-native-vector-icons/MaterialIcons'
import React, { Component } from 'react'
let mounted = false
#inject('UserStore', 'NavigationStore')
#observer
class DynamicList extends Component {
constructor(props) {
super(props)
this.state = {
data: props.data,
currentSearch: props.currentSearch,
}
}
componentWillReceiveProps(nextProps) {
if (nextProps.data !== this.state.data) {
this.setState({ data: nextProps.data, currentSearch: nextProps.currentSearch })
}
}
_renderSuggestion = ({ item, index }) => {
console.log('_renderSuggestion', item)
const splittedName = item.split(' ')
let splittedSearch = this.state.currentSearch.toUpperCase().split(' ')
splittedSearch = splittedSearch.map(x => x.trim()).filter(x => x.length > 1)
let suggestion = []
if (splittedSearch.length == 0) {
suggestion = splittedName.map((word, index) => <Text key={index}>{word} </Text>)
} else {
let highlightedWords = []
splittedName.forEach((word, index) =>
splittedSearch.forEach(wordFromSearch => {
const currentWord = word.toUpperCase()
const isAlreadyHighlighted = highlightedWords.includes(currentWord)
if ((currentWord.includes(wordFromSearch.toUpperCase()) && this.state.currentSearch.length > 0) || isAlreadyHighlighted) {
let v = (
<Text key={index} style={{ color: '#2eb872' }}>
{word}{' '}
</Text>
)
if (!isAlreadyHighlighted) {
highlightedWords.push(currentWord)
}
suggestion[index] = v
} else {
let v = <Text key={index}>{word} </Text>
suggestion[index] = v
}
})
)
}
return (
<TouchableOpacity
style={Style.suggestionView}
onPress={() => {
this.props.UserStore.addRecentSearch(item)
this.props.NavigationStore.navigate({ routeName: 'ProductInfo', params: { item } })
//this.props.NavigationStore.navigate({ routeName: 'SearchResult', params: { item: item } })
this.autoCompleteTimeout = setTimeout(() => {
if (mounted) this.setState({ showAutoComplete: false })
}, 400)
}}
>
<Icon name='search' size={20} style={{}} />
<Text style={{ marginLeft: 20, textAlign: 'left', color: '#9B999A' }}>{suggestion}</Text>
</TouchableOpacity>
)
}
render() {
console.log('data:', this.state.data)
return (
<View style={{ paddingVertical: 10 }}>
<FlatList initialNumToRender={20} data={this.state.data} keyExtractor={(item, index) => item.toString()} renderItem={this._renderSuggestion} keyboardShouldPersistTaps='always' />
</View>
)
}
}
let Results = props => {
console.log(props)
switch (props.navigation.state.key) {
case 'Products': {
let data = props.screenProps.data.suggestions.products.map(pr => pr.product_title)
return <DynamicList data={data} currentSearch={props.screenProps.currentSearch} />
break
}
case 'Brands': {
let data = props.screenProps.data.suggestions.warehouses.map(pr => pr.warehouse_name)
return <DynamicList data={data} currentSearch={props.screenProps.currentSearch} />
break
}
case 'Categories': {
let data = props.screenProps.data.suggestions.categories.map(pr => pr.categories)
return <DynamicList data={data} currentSearch={props.screenProps.currentSearch} />
break
}
case 'UPC': {
let data = props.screenProps.data.suggestions.upcs.map(pr => pr.product_title)
return <DynamicList data={data} currentSearch={props.screenProps.currentSearch} />
break
}
case 'Tags': {
let data = props.screenProps.data.suggestions.tags.map(pr => pr.product_title)
return <DynamicList data={data} currentSearch={props.screenProps.currentSearch} />
break
}
}
return <Text>Home</Text>
}
const TabNavigator = createMaterialTopTabNavigator(
{
Products: Results,
Brands: Results,
Categories: Results,
UPC: Results,
Tags: Results,
},
{
tabBarOptions: {
style: {
backgroundColor: 'black',
},
labelStyle: {
fontSize: 9,
margin: 0,
padding: 0,
fontFamily: 'Poppins-bold',
},
// etc
},
}
)
let f = Component => {
let r = props => {
// alert(props)
return <Component {...props} />
}
return r
}
export default createAppContainer(TabNavigator)
i want to press on item and it will show me the info of it on "ProductInfo"
You have not {} around the map. You also need to check props.screenProps.suggestions and props.screenProps.suggestions.products for null or undefined.
<View style={styles.container}>
{this.props.screenProps.suggestions.products.map(pr => <Text>{pr.product_id}</Text>)}
</View>
Please comment if you have any error when rendering.

How to set state key value pair dynamically in react native?

I am developing an ecommerce app where i need to show product options like Size, color etc.
These options are coming dynamically from API.
I am using Picker component of react native to show option values so that user can choose a value.
Now issue is i select a value, it does not reflect in picker value because i don't know that how to define state variables for pickers dynamically.
so that i can update state values when picker onchangevalue is called.
Initially state looks like this:
state = {
options: {}
}
Now i want that this should dynamically add options to this blank object so it will look like this:
state = {
options: {
Size: '0.5"',
Colour: 'White Dudhiya'
}
}
And after I'll create it then How to access these state variables in any other function.
Please correct me if i am moving in wrong direction and share the correct way to achieve the same.
Please let me know if you need more information from my side.
Any help appreciated.
Thanks
Edit:
This is how i am rendering product options and their values dynamically:
renderOptions(data) {
if (data.options.length > 0) {
var allOptions = data.options.map((item) => {
if (item.product_option_value.length > 0) {
return (
<View key={item.option_id} style={{ marginLeft: 10, marginRight: 10, marginBottom: 15, width: windowWidth - 20 }}>
<MyAppText>{item.name}</MyAppText>
<View style={{ borderWidth: 1, borderColor: '#E8E8E8', marginTop: 5, height: 50 }}>
<Picker
selectedValue={this.state.options[item.name]}
style={{ height: 50, width: '100%' }}
onValueChange={(itemValue, itemIndex) =>
this.setState(() => {
key = item.name;
return {key: itemValue};
})
}
>
{this.renderOptionValues(item)}
</Picker>
</View>
</View>
);
} else {
return;
}
});
return allOptions;
}
}
renderOptionValues(option) {
if (option.product_option_value.length > 0) {
return (option.product_option_value.map((optionValue) => {
return (
<Picker.Item key={optionValue.option_value_id} label={entities.decode(optionValue.name)} value={optionValue.option_value_id} />
);
}));
}
}
I call renderOptions() function inside my render() function.
Take a look at the following implementation, I just tried with some hypothetical values and it worked fine.
class DynamicOptions extends React.Component {
constructor(props) {
super(props);
this.state = {};
}
renderOptions = (options = []) => {
return options.map(option => {
return <Picker.Item label={option.label} value={option.value} key={option.key}/>
});
}
render() {
const {
options
} = this.props;
console.log(this.state);
return ( <
View style = {{ flex: 1 }} >
{
options.map((item, index) => {
return (
<View style={{flex: 1}}>
{
options.map((item, index) => {
return (
<View key={`item-${index}`}>
<Text>{item.name}</Text>
<Picker
selectedValue={this.state[item.name]}
style={{ height: 50, width: '100%' }}
onValueChange={(listItem, index) => {
this.setState({
[item.name]: listItem
});
}}
>
{ this.renderOptions(item.options) }
</Picker>
</View>
)
})
}
</View>
)
}
}
export default DynamicOptions;
Following data I have used to render options (I am not sure what data you are using)
const options = [
{
name: 'Color',
options: [{label: 'Red', value: 'Red', key: 'Red'}, {label: 'Green', value: 'Green', key: 'Green'}]
},
{
name: 'Size',
options: [{label: '1', value: '1', key: '1'}, {label: '2', value: '2', key: '2'}]
}
];
This is how I have called that function
<DynamicOptions options={options}/>
Hope this will help!
according to https://stackoverflow.com/a/35398253/2083099 , I believe you need something like this,
import React, { Component } from 'react';
import { Platform, StyleSheet, Text, View, FlatList, Image, TouchableOpacity, Dimensions, Picker } from 'react-native';
export default class Test extends Component {
constructor() {
super();
this.state = {
services: [],
selectedService: 'a'
}
}
componentDidMount() {
//replace api request instead of setTimeout and then change the services data with setState
setTimeout(() => {
this.setState({
services: [ 'one', 'two', 'three', 'four', 'five' ]
})
}, 3000)
}
render() {
return (
<View>
<Text>Pick a service</Text>
<Picker
selectedValue={this.state.selectedService}
onValueChange={(service) => (this.setState({ selectedService: service }))} >
{this.state.services.map((s, i) => {
return <Picker.Item key={i} value={s} label={s} />
})}
</Picker>
</View>
);
}
}

nativebase autocomplete Unable to find

I'm new to React Native & I'm using NativeBase to build my demo app. I'm not able to create AutoComplete Searchbox using nativebase. Can anyone help me to give any example? My Requirement:
1. Rounded Search Box
2. Once Click it should show cancel button
3. After typing 2 letter it should give provide option to user for select
4. Select the option.
I searched in Google. However unable to find anything which suffice my requirement. Can anyone please help.
for your exact requirement you can write your own code. I tried to write autocomplete functionality. You can check in Expo.
This is basic code for react-native autocomplete functionality.
import React, { Component } from 'react';
import { FlatList, StyleSheet, Text, TextInput, View, TouchableOpacity } from 'react-native';
export default class AutoCompleteBasics extends Component {
constructor(props) {
super(props);
this.state = {
text: '',
textInputFocus: false,
arrayList: ['Apple', 'Mango', 'Guava', 'Muskmelon', 'Watermelon', 'Orange', 'Sapota']
};
}
componentDidMount() {
this.updateDataWithKey();
}
updateDataWithKey() {
const { arrayList } = this.state;
const dataWithKey = arrayList.map(data => {
return {'key': data}
});
this.setState({dataWithKey, filterData: dataWithKey});
}
changeText(text) {
this.setState({text});
const { dataWithKey } = this.state;
if (text !== '') {
let filterData = dataWithKey.filter(obj => {
return obj.key.toLowerCase().indexOf(text.trim().toLowerCase()) > -1;
});
if (filterData.length === 0) {
filterData = [{key: 'No Filter Data'}];
}
this.setState({filterData});
} else {
this.setState({filterData: dataWithKey});
}
}
onListItemClicked(text) {
this.setState({
text,
textInputFocus: false,
filterData: [{key: text}]
});
}
renderRow(item) {
return (
<TouchableOpacity
onPress={() => this.onListItemClicked(item.key)}
style={styles.listItem}
>
<Text style={styles.item}>{item.key}</Text>
</TouchableOpacity>
);
}
handleInputFocus() {
this.setState({textInputFocus: true});
}
handleInputBlur() {
this.setState({textInputFocus: false});
}
render() {
const { filterData, textInputFocus } = this.state;
return (
<View style={styles.container}>
<TextInput
style={styles.textInput}
onFocus={() => this.handleInputFocus()}
onBlur={() => this.handleInputBlur()}
placeholder="Search & Select List!"
onChangeText={(text) => this.changeText(text)}
value={this.state.text}
/>
{textInputFocus &&
<FlatList
data={filterData}
renderItem={({item}) => this.renderRow(item)}
/>
}
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
paddingHorizontal: 8,
paddingTop: 12
},
textInput: {
height: 40,
marginLeft: 5,
},
item: {
padding: 10,
fontSize: 18,
height: 44,
},
})
you may use native-base-autocomplete the api is taken from react-native-auto-complete. check out snack example of how to use it.

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