Send data from React Native component to WebView - react-native

I really tried to make a connection between my react native component and my webview but it doesn't work . Have you any solution ? Here is my code :
let Script = `
document.getElementById("input").addEventListener("focus", function(data)
{alert(data.data)})
`;
render(){
return(
<View>
<WebView
style={{ flex: 1 }}
source={{
html:
'</br></br></br></br><form > <input id="input" class="input"
type="text"
placeholder="Product barcode "/></form>'
}}
keyboardDisplayRequiresUserAction={false} //ios
autoFocus={true} //android
injectedJavaScript={Script1}
automaticallyAdjustContentInsets={false}
allowFileAccessFromFileURLs={true}
scalesPageToFit={false}
mixedContentMode={"always"}
javaScriptEnabled={true}
javaScriptEnabledAndroid={true}
startInLoadingState={true}
onMessage={event => {
alert("HI")
}}
onLoad={() => {}}
/>
<Button
onPress={ this.refs.WEBVIEW_REF.postMessage("Hello from RN");}
title="Scan Barcode"
color="#6495ED"
/>
</View> })
I want just to dispatch the alert after clicking on the button so when i focus the input of the WebView .

you can try wrap webview into TouchableWithoutFeedback

Related

KeyboardAvoidingView, ScrollView and Flatlist in a form

I have a form where I am using KeyboardAvoidingView and ScrollView so that when a user clicks on an input field the screen will scroll to that particular field
Within my form I have an input field that is searchable and I am using a FlatList to display the results for the user to choose from. Currently I am getting the error:
VirtualizedLists should never be nested inside plain ScrollViews
I've looked at many posts around this but am yet to find a solution (unless I've missed something):
1 - How to put FlatList inside of the ScrollView in React-native?
2 - FlatList inside ScrollView doesn't scroll
3 - How to make a FlatList scrollable inside of a ScrollView in react native?
This is what I have so far:
export const SignUpMember = ({navigation}) => {
const renderHeader = formikProps => {
return (
<>
<FormField
keyboardType={'default'}
fieldName={'firstName'}
label={'First Name'}
/>
<FormField
keyboardType={'default'}
fieldName={'lastName'}
label={'Last Name'}
/>
<FormField
onChangeText={text => {
formikProps.values.clubName = text;
searchItems(text);
}}
value={formikProps.values.clubName}
keyboardType={'default'}
fieldName={'clubName'}
label={'Club Name'}
placeholder={'Search Club By Name...'}
/>
</>
);
};
const renderFooter = formikProps => {
return (
<>
<FormField
keyboardType={'phone-pad'}
fieldName={'telephone'}
label={'Telephone'}
/>
<FormField
keyboardType={'email-address'}
fieldName={'email'}
label={'Email'}
/>
<FormField
keyboardType="default"
secureTextEntry={true}
fieldName={'password'}
label={'Password'}
type={'password'}
/>
<FormField
keyboardType="default"
secureTextEntry={true}
fieldName={'passwordConfirmation'}
label={'Confirm Password'}
type={'password'}
/>
<Button
mt="2"
bg="brand.blue"
type="submit"
onPress={formikProps.handleSubmit}>
Sign Up
</Button>
</>
);
};
return (
<KeyboardAvoidingView
keyboardVerticalOffset={headerHeight}
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}>
<ScrollView
_contentContainerStyle={styles.container}
nestedScrollEnabled={true}>
<Box p="1" py="8" w="90%" maxW="290">
<VStack space={3} mt="5">
<Formik
initialValues={initialFormValues}
onSubmit={values => handleFormSubmit(values)}
validationSchema={userValidationSchema}>
{formikProps => (
<View>
<FlatList
nestedScrollEnabled={true}
data={flatListData}
renderItem={({item}) => (
<Pressable
onPress={() => {
formikProps.values.clubName = item.name;
setFlatListData([]);
}}>
<Text style={styles.flatList}>{item.name}</Text>
</Pressable>
)}
keyExtractor={item => item.name}
ListHeaderComponent={renderHeader(formikProps)}
ListFooterComponent={renderFooter(formikProps)}
/>
</View>
)}
</Formik>
</VStack>
</Box>
</ScrollView>
</KeyboardAvoidingView>
);
};
export default SignUpMember;
How can I piece this together?

Flatlist Items flicker and then disappear

I have a Flatlist that is supposed to represent items.
Yesterday the Flatlist worked without problems, and today it started flashing heavily when rendering and when the screen is called up again, only the last item is displayed.
The data is pulled async in this screen via axios from an API
I then rebuilt the Flatlist to the minimum status, but the error remains.
<FlatList
data={packages}
horizontal
showsHorizontalScrollIndicator={false}
keyExtractor={(item) => item.id}
snapToInterval={packageCardWidth}
bounces={false}
decelerationRate={0}
renderItem={({ item, index }) => {
return (
<PackageCard
containerWidth={packageCardWidth}
{...item}
/>
);
}}
/>
The code for the rendered item
export default function PackageCard(props) {
return (
<View style={[tw.style('flex-1'), { width: props.containerWidth }]}>
<View
style={[
tw.style(
'bg-white rounded-lg shadow-md pb-4 m-3 overflow-hidden'
),
{},
]}
>
<Image
source={{
uri: 'https://images.unsplash.com/photo-1577705998148-6da4f3963bc8?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=987&q=80',
}}
style={tw.style('h-64 w-full mb-4')}
/>
<View style={tw.style('px-3 p-2')}>
<Text style={tw.style('text-xl font-semibold')}>
{props.name}
</Text>
</View>
</View>
</View>
);
}

Focus the input in the WebView with React native

Have you any idea to create a onFocus event in this input of the WebView ?
export default class App extends Component {
render() {
return (
<View style={styles.container}>
<WebView
originWhitelist={['*']}
source={{ html: ' </br></br><form> <input type="text"
placeholder="name" onFocus=(*****)/> <input
type="text" placeholder="surname"/> <Button>Submit</Button>
</form>' }} />
</View>
)}}
I tried the usual onFocus but it doesn't work . I want to dispatch an event when i focus the input
To make a onFocusEvent to the input of the webview we have just to deal with postMessage and onMessage . Here is the full code :
let Script = `
document.getElementById("input").addEventListener("focus", function() {
var data = {
type: "OnFocusEvent",
message : "OnFocusEvent"
};
window.postMessage(JSON.stringify({data}),"*");
});
`;
<WebView
style={{ flex: 1 }}
source={{
html:
'</br></br></br></br><form > <input id="input" class="input" type="text"
placeholder="Product barcode "/></form>'
}}
keyboardDisplayRequiresUserAction={false} //ios
autoFocus={true} //android
injectedJavaScript={Script1}
automaticallyAdjustContentInsets={false}
allowFileAccessFromFileURLs={true}
scalesPageToFit={false}
mixedContentMode={"always"}
javaScriptEnabled={true}
javaScriptEnabledAndroid={true}
startInLoadingState={true}
onMessage={event => {
alert("You can do here whatever you want")
}}
onLoad={() => {}}
/>
There is closed Pull Request for that feature. For now, you can use react-native-enhance-webview
I hope that helps. Good luck.

react-native dynamic activity indicator

I have multiple videos from an array map that each have an activity indicator. I want to set to false once the video is loaded.
Can someone please explain a method where I can do this for each video individually. At the moment on the onLoad callback it's just setting a global state value.
{revArray.map((camera,index) => (
<View key={'camera'+index} style={{backgroundColor:'#eeeeee'}}>
<TouchableOpacity onPress={() => {this.removePrompt(camera.title.toString())}} style={{padding:6,position:'absolute',right:4,top:8,zIndex:999}}><Image source={require('../Images/delete1.png')} style={{width:16,height:16}}></Image></TouchableOpacity>
<Text key={'title'+index} style={{color:'#113b92',textAlign:'center',padding:10,fontSize:16,fontFamily:'Lato-Bold'}}>{camera.title}</Text>
<View style={{backgroundColor:'#000'}}>
{this.state.isLoading ? ( <View style={{ position: 'absolute',left: 0,right: 0,top: 0,bottom: 0,alignItems: 'center',justifyContent: 'center',zIndex:9999}}>
<ActivityIndicator size="large" color={'#000'} style={{backgroundColor:'#fff', padding:6, borderRadius:30}} />
</View>
): (null)}
<Video
onLoad={()=>{this.setState({isLoading:false})}}
key={'video'+index}
ref={(ref: Video) => { this.video = ref }}
style={styles.fullScreen}
resizeMode='cover'
source={{uri: camera.video+'?'+new Date()}}
repeat={true}
/>
</View>
</View>
))}
Because isLoading is the state of the component rendering each of the videos in the array its only ever going to control all of them... What you want to do here is render a "container" component with its own state for each of these -
class VideoWrapper extends React.Component {
state = {
isLoading: true
}
<View key={'camera'+index} style={{backgroundColor:'#eeeeee'}}>
...
<Video
onLoad={()=>{this.setState({isLoading:false})}}
key={'video'+index}
ref={(ref: Video) => { this.video = ref }}
style={styles.fullScreen}
resizeMode='cover'
source={{uri: camera.video+'?'+new Date()}}
repeat={true}
/>
</View>
}
And to render -
{revArray.map((camera,index) =>
<VideoWrapper key={camera.id} camera={camera} index={index} />
)}
This way each video in the array controls its own state.

How to add onPress events on Cards (on native base)?

I'm trying to make those cards clickable to redirect to another screen, but I cant figure it out
let cards = this.state.items.map(item => (
<Card key={item.id} onPress={() => Actions.dogScreen()}>
<CardItem bordered>
<Left>
<Thumbnail square source={item.image ? { uri: "data:image/jpeg;base64," + item.image } : logo} />
<Body>
<Text>Name: {item.name}, Age: {item.age}</Text>
<Text note>Gender: {item.gender.name} Race: {item.race.name}</Text>
</Body>
</Left>
</CardItem>
</Card>))
You can make <Card /> clickable by wrapping the whole card by TouchableOpacity. Also don't forget to add pointerEvents="none" for each card.
import { TouchableOpacity } from 'react-native';
let cards = this.state.items.map(item => (
<TouchableOpacity key={item.id} onPress={() => Actions.dogScreen()}>
<Card pointerEvents="none">
<CardItem bordered>
<Left>
<Thumbnail square source={item.image ? { uri: "data:image/jpeg;base64," + item.image } : logo} />
<Body>
<Text>Name: {item.name}, Age: {item.age}</Text>
<Text note>Gender: {item.gender.name} Race: {item.race.name}</Text>
</Body>
</Left>
</CardItem>
</Card>
</TouchableOpacity>
))