Weird padding on View in react native web on Edge - javascript

I was creating a Button in react native (on web). If I view the button in Edge, a very weird padding appears. I tried to debug but I can't get a fix. It works correctly on Android and Firefox.
I think there is some problem with Edge's renderer (Blink) because the code works correctly in firefox and on android (native).
Here is the code for the component:
import React, { useState } from 'react';
import { View, Animated, Easing, Image, StyleSheet, Pressable, Text } from 'react-native';
import { Hoverable } from 'react-native-web-hooks';
const Button = () => {
const [animatedButtonPressed] = useState(new Animated.Value(0));
const [animatedButtonHover] = useState(new Animated.Value(0));
const animate = (value, toValue, duration = 150, easing = Easing.linear) => {
Animated.timing(value, {
toValue: toValue,
duration: duration,
easing: easing,
// change later
useNativeDriver: false
}).start();
}
const animatedTextStyle = {
color: animatedButtonPressed.interpolate({
inputRange: [0,1],
outputRange: ["#fff" , "#2b7f3c"]
})
}
const animatedButtonStyle = {
backgroundColor: animatedButtonHover.interpolate({
inputRange: [0,1],
outputRange: ["#2b7f3c", "transparent"]
}),
}
const animatedButtonPressedStyle = {
backgroundColor: animatedButtonPressed.interpolate({
inputRange: [0,1],
outputRange: ["#fff", "red"]
}),
}
let Handlers = (props) => {
return (
<>
<Pressable onPressIn={() => animate(animatedButtonPressed, 1)} onPressOut={() => animate(animatedButtonPressed, 0)}>
<Hoverable onHoverIn={() => animate(animatedButtonHover, 1)} onHoverOut={() => animate(animatedButtonHover, 0)}>
<View {...props}/>
</Hoverable>
</Pressable>
</>
)
}
let Backgrounds = (props) => {
return (
<Animated.View style={animatedButtonPressedStyle}>
<Animated.View style={animatedButtonStyle}>
<View {...props}/>
</Animated.View>
</Animated.View>
)
}
return (
<View style={styles.container}>
<View style={styles.button}>
<Backgrounds>
<Handlers>
<View style={styles.padding}>
<Animated.Text style={[styles.text, animatedTextStyle]}>Hello</Animated.Text>
</View>
</Handlers>
</Backgrounds>
</View>
</View>
);
};
const styles = StyleSheet.create({
container: {
flexDirection: 'row',
alignSelf: 'flex-start',
overflow: 'hidden',
},
button: {
borderRadius: 3,
borderWidth: 2,
borderColor: 'green',
},
padding: {
paddingHorizontal: 10,
paddingVertical: 5,
},
text: {
color: 'white',
fontSize: 16
}
});
export default Button;

I think this is unfortunately a symptom of using React-native on the web things get squashed and you won't have as much control for cross browser quirks.
Is there any reason you didn't use ReactJS?

Related

in react-native how to use body-pix

import { Camera, CameraType } from 'expo-camera';
import React, { useRef } from "react";
// import logo from './logo.svg';
import * as tf from "#tensorflow/tfjs";
import * as bodyPix from "#tensorflow-models/body-pix";
import { useState } from 'react';
import { Button, StyleSheet, Text, TouchableOpacity, View } from 'react-native';
//AFTER IMPORT
export default function App() {
const [type, setType] = useState(CameraType.back);
const [permission, requestPermission] = Camera.useCameraPermissions();
const canvasRef = useRef(null);
//next part
const runBodysegment = async () => {
const net = await bodyPix.load();
console.log("BodyPix model loaded.");
// Loop and detect hands
setInterval(() => {
detect(net);
}, 100)
};
//next part
const detect = async (net) => {
const person = await net.segmentPersonParts(video);
console.log(person);
const coloredPartImage = bodyPix.toColoredPartMask(person);
bodyPix.drawMask(
canvasRef.current,
video,
coloredPartImage,
0.7,
0,
false
);
runBodysegment();
if (!permission) {
// Camera permissions are still loading
return <View />;
}
if (!permission.granted) {
// Camera permissions are not granted yet
return (
<View style={styles.container}>
<Text style={{ textAlign: 'center' }}>We need your permission to show the camera</Text>
<Button onPress={requestPermission} title="grant permission" />
</View>
);
}
function toggleCameraType() {
setType(current => (current === CameraType.back ? CameraType.front : CameraType.back));
}
return (
<View style={styles.container}>
<Camera style={styles.camera} type={type}>
<View style={styles.buttonContainer}>
<TouchableOpacity style={styles.button} onPress={toggleCameraType}>
<Text style={styles.text}>Flip Camera</Text>
</TouchableOpacity>
</View>
</Camera>
</View>
);
}
//next part
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
},
camera: {
flex: 1,
},
buttonContainer: {
flex: 1,
flexDirection: 'row',
backgroundColor: 'transparent',
margin: 64,
},
button: {
flex: 1,
alignSelf: 'flex-end',
alignItems: 'center',
},
text: {
fontSize: 24,
fontWeight: 'bold',
color: 'white',
},
});
};
I want to use body-pix in my react-native app for android .
can any one help me how to do it .
I want my app to open a camera and in my camera there will be a body body-pix working
in my android app
I want my react-native app to work properly with body-pix
I had try it many time time but I can't do it properly

How to create a bottom tab navigation above bottomsheet in react native?

I am trying to create a bottom tab navigation in react native which is having a blur effect but as I am using it above the bottomsheet so navigation bar is getting hide or will have to manage with bottomInset property of bottomsheet.
This is tab navigation coming above bottom sheet
This is actually I want it to look
<BottomSheet
ref={bottomSheetRef}
visible={bottomSheetVisible}
onChangeCallback={onChangeCallback}
enablePanDownToClose={false}
header={header}
bottomInset={84} // due to this I am able to add it above the bottomsheet
style={styles.bottomSheet}
renderBackdrop={renderBackdrop}>
</BottomSheet>
Custom Backdrop
const CustomBackdrop = ({animatedIndex, style}: BottomSheetBackdropProps) => {
// animated variables
const containerAnimatedStyle = useAnimatedStyle(() => ({
opacity: interpolate(
animatedIndex.value,
[1, 1],
[1, 1],
Extrapolate.CLAMP,
),
}));
// styles
const containerStyle = useMemo(
() => [style, styles.container, containerAnimatedStyle],
[style, containerAnimatedStyle],
);
return (
<Animated.View style={containerStyle}>
<View>
<WalletHomeHeader />
<WalletHomeCard />
</View>
<NavigationBar />
</Animated.View>
);
};
export default CustomBackdrop;
const styles = StyleSheet.create({
container: {
flexDirection: 'column',
justifyContent: 'space-between',
},
});
Style in Tab Navigator
tabBarActiveTintColor: theme.white,
tabBarInactiveTintColor: theme.secondaryGrey,
tabBarStyle: {
position: 'absolute',
bottom: 0,
paddingVertical: scaleHeight(15),
backgroundColor: convertHexToRGBA(theme.neutral_700, 0.5),
borderTopWidth: 1,
borderTopColor: theme.grey,
},

create variable dynamically in react-native component

i need to create a variable in a react-native component, which i want to use several times...each instance of this component needs to have a different variable name to reference to.
<View ref={view => { shapeView = view; }}
onLayout={({ nativeEvent }) => {
shapeView.measure( (x, y, width, height, pageX, pageY) => {
console.log('- - - DEBUG: width:' + width + ', pageX:'+ pageX + ', pageY:' + pageY);
let shapePickerPosition = {w: width, x: pageX, y: pageY};
setShapeCoords(shapePickerPosition);
})
}}>
as i said, i want to use this code inside a component, and this component several times, and if i don't change die variable: "shapeView" i end up with just the coordinates from the last instance of that component..
here's the whole component:
import React, {useState, useEffect} from 'react';
import {StyleSheet, View, Text, Modal, TouchableOpacity, Pressable, FlatList} from 'react-native';
import { useTheme} from '#react-navigation/native';
// ------------------PickerRow-----------------------------------------------------------------------
function CustomPickerRow(props) {
const { colors } = useTheme(); // works
const theme = useTheme();
const [selectedItem, setSelectedItem] = useState('choose');
const [coordinates, setCoordinates] = useState();
const setItem = (value) => {
// set parent state
props.action(value)
}
return (
<View
ref = { view => { shapeView = view; } }
onLayout={({ nativeEvent }) => {
shapeView.measure( (x, y, width, height, pageX, pageY) => {
console.log('height:', height);
console.log('width:', width);
console.log('x:', pageX);
console.log('y:', pageY);
let coords = {w: width, x: pageX, y: pageY};
setCoordinates(coords);
})
}}
style = {{
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
height: 25,
paddingLeft: 5,
marginBottom: 3,
backgroundColor: colors.frameBackground,
borderColor: colors.borderColor,
borderWidth: 1,
borderRadius: 5}}>
<View style = {styles.icon} >
<Text style = {styles.text}>{props.icon}</Text>
</View>
<View style = {styles.description} >
<Text style = {{fontSize: 11, fontWeight: 'bold', color: colors.text, textAlign: 'left', marginLeft: 5,}}>{props.title}</Text>
</View>
<MyPicker data={props.data} action={setItem} position={coordinates}/>
</View>
);
}
// ------------------MyPicker-----------------------------------------------------------------------
function MyPicker(props) {
const { colors } = useTheme(); // works
const theme = useTheme();
const [isVisible, setIsVisible] = useState(false);
const [selectedItem, setSelectedItem] = useState(props.data[0].key)
const [coordinates, setCoordinates] = useState({w: 180, x: 0, y: 0});
useEffect(() => {
if (props.position) {
setCoordinates(props.position);
}
})
const setItem = item => {
// set parent state
props.action(item.value);
setIsVisible(false);
console.log("chosen value = " + item.key);
setSelectedItem(item.key);
}
const showPicker = () => {
setIsVisible(true);
}
const renderItem = ({item}) => {
return <View>
<Pressable onPress={() => setItem(item)}>
<Text style={{color: colors.text, fontSize: 17, alignSelf: 'center', paddingTop: 3}}>
{item.key}
</Text>
</Pressable>
</View>
}
return (
<View style={{flex:5, backgroundColor: 'transparent'}}>
<TouchableOpacity onPress={showPicker}>
<Text style={{color: colors.textSubtitleColor, fontSize: 11, alignSelf: 'flex-end', paddingRight: 10}}>
{selectedItem}
</Text>
</TouchableOpacity>
<Modal animationType="fade"
transparent={true}
visible={isVisible}
style={styles.testPicker}
onRequestClose={() => {
console.log('Modal has been closed.');
}}
>
<View style={{ backgroundColor: colors.frameBackground,
borderColor: colors.borderColor,
borderWidth: 1,
borderRadius: 5,
position: 'absolute',
width: 180,
height: 200,
left: coordinates.x, //100,
top: coordinates.y //160
}}>
<FlatList
data={props.data}
renderItem={renderItem}
/>
</View>
</Modal>
</View>
);
}
const styles = StyleSheet.create({
testPicker: {
backgroundColor: 'gray',
position: 'absolute',
width: 112,
height: 200,
left: 100,
top: 160
},
icon: {
flex: 1,
backgroundColor: '#00529F',
marginRight: 0,
borderRadius: 5
},
description: {
flex: 2,
height: 17,
backgroundColor: 'transparent',
marginRight: 0,
borderRadius: 5
},
});
export default CustomPickerRow;
and i call that component like this:
<CustomPickerRow id='shapePicker' icon='2' title='Shape:' data={shapeItems} action={setShape} selectedItem={selectedShape} visible={modalVisible} />```
shapeView should be a ref like this:
const MyComponent = () => {
const shapeView = useRef();
return (
<View
ref={view => shapeView.current = view}
/* could also look like this: ref={shapeView} */
onLayout={({nativeEvent}) => {
shapeView.current.measure(...);
}
/>
)
}
It SHOULD NOT be like this:
let shapeView; // this is outside your component - it shouldn't be here
const MyComponent = () => {
return (
<View
ref={view => shapeView = view}
onLayout={({nativeEvent}) => {
shapeView.measure(...);
}
/>
)
}
In a class based component it could look like this:
class MyComponent extends React.Component {
constructor() {
this.shapeView = React.createRef();
}
render() {
return (
<View
ref={this.shapeView}
onLayout={({nativeEvent}) => {
this.shapeView.current.measure(...);
}
/>
)
}
}

When animating and changing state, the animation disappears(react native)

I am using react native with expo cli and I have a component:
import React, {useEffect, useState} from 'react'
import {View, TextInput, Text, TouchableOpacity, Animated, Easing} from 'react-native';
import s from './Login_style'
import {connect} from "react-redux";
const LoginInner = (props) => {
const [mode, setMode] = useState(true)
const btnAnim = new Animated.Value(0)
const setModeAnim = (is) => {
if (is) {
Animated.timing(btnAnim, {
toValue: 1,
duration: 300,
easing: Easing.out(Easing.exp),
useNativeDriver: false,
}).start()
// setMode(false)
} else {
Animated.timing(btnAnim, {
toValue: 0,
duration: 300,
easing: Easing.out(Easing.exp),
useNativeDriver: false
}).start()
// setMode(true)
}
}
const size1 = btnAnim.interpolate({
inputRange: [0, 1],
outputRange: ['30%', '60%']
})
const size2 = btnAnim.interpolate({
inputRange: [0, 1],
outputRange: ['60%', '30%']
})
return (
<View style={s.page}>
<View style={s.inputs}>
<Text style={[s.text, s.title]}>{mode ? 'Вход' : 'Регистрация'}</Text>
<View style={s.textInput}>
<View>
<Text style={[s.text, s.placeholder]}>Логин</Text>
</View>
<TextInput style={s.input}/>
</View>
<View style={s.textInput}>
<View>
<Text style={[s.text, s.placeholder]}>Пароль</Text>
</View>
<TextInput style={s.input}/>
</View>
<View style={s.actions}>
<Animated.View style={[s.btn, s.loginBtn, {width: size2}]}>
<TouchableOpacity style={s.touchableBtn} onPress={() => {
setModeAnim(false)
}}>
<Text style={s.loginBtn_text}>{mode ? 'Вход' : '<--'}</Text>
</TouchableOpacity>
</Animated.View>
<Animated.View style={[s.btn, s.regBtn, {width: size1}]}>
<TouchableOpacity style={s.touchableBtn} onPress={() => {
setModeAnim(true)
}}>
<Text style={s.loginBtn_text}>{mode ? '-->' : 'Регистрация'}</Text>
</TouchableOpacity>
</Animated.View>
</View>
</View>
</View>
)
}
const Login = connect((state) => {
return {}
}, {})(LoginInner)
export default Login
Here I am interested in this function
const setModeAnim = (is) => {
if (is) {
Animated.timing(btnAnim, {
toValue: 1,
duration: 300,
easing: Easing.out(Easing.exp),
useNativeDriver: false,
}).start()
// setMode(false)
} else {
Animated.timing(btnAnim, {
toValue: 0,
duration: 300,
easing: Easing.out(Easing.exp),
useNativeDriver: false
}).start()
// setMode(true)
}
}
I run the animation here when the function is executed (ignore the commented out line for now). The animation really works.
VIDEO DEMONSTRATION: https://youtu.be/fiGy0gNej68
But if I change the state of the component in this function after starting the animation:
setMode(false) or setMode(true) animation does not start, even the buttons do not change their size
VIDEO DEMONSTRATION: https://youtu.be/deLZEKVnaBY
Tell me how to solve this
Thanks
To add to #LIMPIX64's answer:
using const btnAnim = React.useRef(new Animated.Value(0)).current solves the problem because since Animated.Value is an instance of a class, you need to wrap it in a useRef call so that it only gets created once when the component renders for the first time (which is what useRef accomplishes). Otherwise, the class could be reinstantiated on a state change and cause the issue you're experiencing
Please do const btnAnim = React.useRef(new Animated.Value(0)).current – Harrison

React Native: Touchable Opacity element is clickable on iOS but not Android

I'm working on a React Native app with a typeahead component. The typeahead displays options that overlay other content on the route (see right image below). When a user clicks one of those options, an onPress listener runs a function:
This all works just fine on iOS. On Android though, the onPress event is never received. Even more strangely, when I try to click on an option lower in the list (like Boston, MA, USA), the onPress event is received by the card below the pressed option (Djerba).
Does anyone know what might cause this behavior? I'd be super grateful for any insights others can offer on this query.
Here's the code for the Explore view and the typeahead components.
Explore.js
import React from 'react'
import { connect } from 'react-redux'
import { Text, View, ScrollView, TouchableOpacity } from 'react-native'
import { gradients, sizing } from '../../style'
import { LinearGradient } from 'expo-linear-gradient'
import { MountainHero } from '../Heros'
import { CardRow } from '../Card'
import Loading from '../Loading'
import { setExploreSearch, onExploreTypeaheadClick } from '../../actions/locations'
import { Typeahead } from '../Typeahead'
const styles = {
container: {
flex: 1,
flexDirection: 'column',
},
scrollView: {
paddingBottom: sizing.margin,
},
loadingContainer: {
position: 'absolute',
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
zIndex: 100,
elevation: 100,
top: 53,
width: '100%',
},
typeahead: {
margin: sizing.margin,
marginBottom: 0,
width: sizing.screen.width - (2*sizing.margin),
zIndex: 100,
elevation: 100,
}
}
const Explore = props => {
const { authenticated: a, spotlight, loading } = props;
let r = (a.recommendedLocations || []);
if (!r || !spotlight) return null;
// remove spotlight locations from the recommended locations
const ids = spotlight.map(i => i.guid);
const recommended = r.filter(i => ids.indexOf(i.guid) == -1);
return (
<LinearGradient style={styles.container} colors={gradients.teal}>
<ScrollView contentContainerStyle={styles.scrollView}>
{loading && (
<View style={styles.loadingContainer}>
<Loading />
</View>
)}
<MountainHero text='Explore' />
<Typeahead
style={styles.typeahead}
placeholder='Search Cities'
value={props.exploreSearch}
onChange={props.setExploreSearch}
vals={props.exploreTypeahead}
valKey={'place_id'}
onTypeaheadClick={props.onExploreTypeaheadClick}
/>
<CardRow
text='Explore Places'
cards={recommended}
type='location' />
<CardRow
text='In the Spotlight'
cards={spotlight}
type='location' />
</ScrollView>
</LinearGradient>
)
}
const mapStateToProps = state => ({
authenticated: state.users.authenticated,
spotlight: state.locations.spotlight,
exploreSearch: state.locations.exploreSearch,
exploreTypeahead: state.locations.exploreTypeahead,
loading: state.locations.loading,
})
const mapDispatchToProps = dispatch => ({
setExploreSearch: s => dispatch(setExploreSearch(s)),
onExploreTypeaheadClick: val => dispatch(onExploreTypeaheadClick(val)),
})
export default connect(mapStateToProps, mapDispatchToProps)(Explore)
Typeahead.js
import React from 'react'
import { Text, View, TouchableOpacity } from 'react-native'
import { sizing, GradientInput } from '../style'
const styles = {
container: {
position: 'absolute',
zIndex: 100,
elevation: 100,
height: 400,
width: '100%',
},
input: {
width: '100%',
borderRadius: 0,
},
typeaheadContainer: {
position: 'absolute',
zIndex: 100,
elevation: 100,
top: 55,
width: '100%',
},
typeaheadRow: {
padding: 10,
paddingTop: 12,
paddingBottom: 12,
borderWidth: 1,
borderColor: '#eeeeee',
backgroundColor: '#ffffff',
marginBottom: -1,
},
typeaheadRowText: {
fontSize: 15,
fontFamily: 'open-sans',
lineHeight: 20,
backgroundColor: '#ffffff',
},
}
export const Typeahead = props => {
return (
<View style={[props.container, props.style]}>
<GradientInput style={styles.input}
placeholder={props.placeholder}
value={props.value}
onChange={props.onChange} />
<TypeaheadList vals={props.vals}
valKey={props.valKey}
onTypeaheadClick={props.onTypeaheadClick} />
</View>
)
}
export const TypeaheadList = props => {
if (!props.vals) return null;
return (
<View style={styles.typeaheadContainer}>
{props.vals.map(i => {
let text = i.text;
if (text.length > 31) text = text.substring(0,31) + '...';
return (
<TouchableOpacity activeOpacity={0.5} key={i[props.valKey]}
style={styles.typeaheadRow}
onPress={() => props.onTypeaheadClick(i[props.valKey])}>
<Text numberOfLines={1} style={styles.typeaheadRowText}>{text}</Text>
</TouchableOpacity>
)
})}
</View>
)
}
export default Typeahead
Try to move Typeahead component below all CardRow components and set position:absolute for Typeahead. Probably on android - the latest view shadow all views before (I am not sure, but I think you have to try it for next discovering issue).
You should also remove position: absolute from all but one component. Working code:
Explore.js
import React from 'react'
import { connect } from 'react-redux'
import { Text, View, ScrollView, TouchableOpacity } from 'react-native'
import { gradients, sizing } from '../../style'
import { LinearGradient } from 'expo-linear-gradient'
import { MountainHero } from '../Heros'
import { CardRow } from '../Card'
import Loading from '../Loading'
import { setExploreSearch, onExploreTypeaheadClick } from '../../actions/locations'
import { Typeahead } from '../Typeahead'
const styles = {
container: {
flex: 1,
flexDirection: 'column',
},
scrollView: {
paddingBottom: sizing.margin,
},
loadingContainer: {
position: 'absolute',
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
zIndex: 1,
elevation: 1,
top: 53,
width: '100%',
},
topCardRow: {
paddingTop: sizing.margin + sizing.gradientInput.height,
},
typeahead: {
margin: sizing.margin,
marginBottom: 0,
width: sizing.screen.width - (2*sizing.margin),
zIndex: 1,
elevation: 1,
position: 'absolute',
top: sizing.mountainHero.height,
left: 0,
}
}
const Explore = props => {
const { authenticated: a, spotlight, loading } = props;
let r = (a.recommendedLocations || []);
if (!r || !spotlight) return null;
// remove spotlight locations from the recommended locations
const ids = spotlight.map(i => i.guid);
const recommended = r.filter(i => ids.indexOf(i.guid) == -1);
return (
<LinearGradient style={styles.container} colors={gradients.teal}>
<ScrollView contentContainerStyle={styles.scrollView}>
{loading && (
<View style={styles.loadingContainer}>
<Loading />
</View>
)}
<MountainHero text='Explore' />
<CardRow
style={styles.topCardRow}
text='Explore Places'
cards={recommended}
type='location' />
<CardRow
text='In the Spotlight'
cards={spotlight}
type='location' />
<Typeahead
style={styles.typeahead}
placeholder='Search Cities'
value={props.exploreSearch}
onChange={props.setExploreSearch}
vals={props.exploreTypeahead}
valKey={'place_id'}
onTypeaheadClick={props.onExploreTypeaheadClick}
/>
</ScrollView>
</LinearGradient>
)
}
const mapStateToProps = state => ({
authenticated: state.users.authenticated,
spotlight: state.locations.spotlight,
exploreSearch: state.locations.exploreSearch,
exploreTypeahead: state.locations.exploreTypeahead,
loading: state.locations.loading,
})
const mapDispatchToProps = dispatch => ({
setExploreSearch: s => dispatch(setExploreSearch(s)),
onExploreTypeaheadClick: val => dispatch(onExploreTypeaheadClick(val)),
})
export default connect(mapStateToProps, mapDispatchToProps)(Explore)
Typeahead.js
import React from 'react'
import { Text, View, TouchableOpacity } from 'react-native'
import { sizing, GradientInput } from '../style'
const styles = {
container: {
zIndex: 1,
elevation: 1,
height: 400,
width: '100%',
},
input: {
width: '100%',
borderRadius: 0,
},
typeaheadContainer: {
zIndex: 1,
elevation: 1,
top: 0,
width: '100%',
},
typeaheadRow: {
padding: 10,
paddingTop: 12,
paddingBottom: 12,
borderWidth: 1,
borderColor: '#eeeeee',
backgroundColor: '#ffffff',
marginBottom: -1,
zIndex: 1,
elevation: 1,
},
typeaheadRowText: {
fontSize: 15,
fontFamily: 'open-sans',
lineHeight: 20,
backgroundColor: '#ffffff',
},
}
export const Typeahead = props => {
return (
<View style={[props.container, props.style]}>
<GradientInput style={styles.input}
placeholder={props.placeholder}
value={props.value}
onChange={props.onChange} />
<TypeaheadList vals={props.vals}
valKey={props.valKey}
onTypeaheadClick={props.onTypeaheadClick} />
</View>
)
}
export const TypeaheadList = props => {
if (!props.vals) return null;
return (
<View style={styles.typeaheadContainer}>
{props.vals.map(i => {
let text = i.text;
if (text.length > 31) text = text.substring(0,31) + '...';
return (
<TouchableOpacity activeOpacity={0.5} key={i[props.valKey]}
style={styles.typeaheadRow}
onPress={() => props.onTypeaheadClick(i[props.valKey])}>
<Text numberOfLines={1} style={styles.typeaheadRowText}>{text}</Text>
</TouchableOpacity>
)
})}
</View>
)
}
export default Typeahead

Categories