how to handle Onpress events in react native snap carousel - javascript

I have a class and in that class I am displaying carousel components like this
sampleclass.js
.
.
.
render{
return (
<Image ..>
<Text>
text
</Text>
<Image ..>
<js file tag where carousel is defined />
</Image>
<Text>
text
</Text>
<Image ..>
<js file tag where carousel is defined />
</Image>
.
.
.
</Image>
);
}
function fname(params..){
I also need to access carousel ref here
}
and I have another class where I have defined the carousel
carouselclass.js
import React, { PureComponent } from 'react';
import { Dimensions, StyleSheet, View } from 'react-native';
import Carousel from 'react-native-snap-carousel';
export default class ExampleCarousel extends PureComponent {
state = {
data: [{}, {}, {}, {}, {}, {}]
}
renderItem = () => (
<View style={styles.tile} />
);
render () {
return (
<View style={styles.container}>
<Carousel
data={this.state.data}
renderItem={this.renderItem}
itemWidth={Dimensions.get('window').width * 0.85}
sliderWidth={Dimensions.get('window').width}
containerCustomStyle={styles.carousel}
slideStyle={{ flex: 1 }}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
height: 300
},
carousel: {
flex: 1,
backgroundColor: 'red'
},
tile: {
flex: 1,
width: Dimensions.get('window').width * 0.85,
backgroundColor: 'yellow'
}
});
I have to handle the onPress event of the carousel swipe components in the function of sampleclass.js
How can I do this I know how to handle onPress events on react native but couldnt do this with react-native-snap-carousel since I am using it for the first time I have read examples given in the docs but couldnt find something related to this

If you want to handle single Carousel item's onPress prop, you need to add that to your render item.
Example
// change this
renderItem = () => (
<View style={styles.tile} />
);
// to this
_onPressCarousel = () => {
// here handle carousel press
}
renderItem = () => (
<TouchableOpacity onPress={this._onPressCarousel} style={styles.tile}>
<Image
style={styles.button}
source={require('./myButton.png')}
/>
</TouchableOpacity>
);

<Carousel
...
renderItem={(carousel, parallaxProps) =>
this._renderItem(carousel, parallaxProps)
}
...
/>
_renderItem(carousel, parallaxProps) {
const { item } = carousel;
return (
<TouchableOpacity
onPress={() => {
this._handlePress(item._id);
}}
>
...

Related

React native, undefined is not an object And handle onChange

I made 2 screens home and editing screen. I want to change values from edit screen without redux and context but I don't know how? and also when I click save in editscreen it's throwing error that undefined is not an object (evaluating '_this.props.navigation.goBack') and displaing blank home screencwhy that's happening. Can some one help me please, below is my code
home.js
class Home extends Component {
state = {
modal: false,
editMode: false.
post: [
{
key: "1",
title: "A Good Boi",
des: "He's a good boi and every one know it.",
image: require("../assets/dog.jpg"),
},
{
key: "2",
title: "John Cena",
des: "As you can see, You can't see me!",
image: require("../assets/cena.jpg"),
},
],
};
addPost = (posts) => {
posts.key = Math.random().toString();
this.setState((prevState) => {
return {
post: [...prevState.post, posts],
modal: false,
};
});
};
onEdit = (data) => {
this.setState({ post: { title: data }, editMode: false });
};
render() {
if (this.state.editMode)
return <EditScreen item={item} onEdit={this.onEdit} />;
return (
<Screen style={styles.screen}>
<Modal visible={this.state.modal} animationType="slide">
<TouchableWithoutFeedback onPress={Keyboard.dismiss}>
<View style={styles.modalContainer}>
<AddPost addPost={this.addPost} />
</View>
</TouchableWithoutFeedback>
</Modal>
<FlatList
data={this.state.post}
renderItem={({ item }) => (
<>
<TouchableOpacity
activeOpacity={0.7}
onPress={() => this.setState({ editMode: true })}
style={styles.Edit}
>
<MaterialCommunityIcons
name="playlist-edit"
color="green"
size={35}
/>
</TouchableOpacity>
<Card>
<Image style={styles.image} source={item.image} />
<View style={styles.detailContainer}>
<Text style={styles.title} numberOfLines={1}>
{item.title}
</Text>
<Text style={styles.subTitle} numberOfLines={2}>
{item.des}
</Text>
</View>
</Card>
</>
)}
/>
</Screen>
Edit.js
import React, { Component } from "react";
import { View, StyleSheet, Image, KeyboardAvoidingView } from "react-native";
import colors from "../config/colors";
import AppButton from "../components/AppButton";
import AppTextInput from "../components/AppTextInput";
class EditScreen extends Component {
render() {
const { item, onEdit, onClose } = this.props;
return (
<KeyboardAvoidingView
behavior="position"
keyboardVerticalOffset={Platform.OS === "ios" ? 0 : 100}
>
<Image style={styles.image} source={item.image} />
<View style={styles.detailContainer}>
<AppTextInput value={item.title} />
<AppTextInput value={item.des} />
</View>
<AppButton
text="Save"
onPress={() => {
onEdit(this.state);
}}
/>
</KeyboardAvoidingView>
);
}
}
export default EditScreen;
AppTextInput.js
function AppTextInput({ icon, width = "100%", ...otherProps }) {
return (
<View style={[styles.container, { width }]}>
<TextInput
placeholderTextColor={defaultStyles.colors.medium}
style={defaultStyles.text}
{...otherProps}
/>
</View>
);
}
Try this:
Edit.js
import React, { Component } from 'react';
import { View, StyleSheet, Image, KeyboardAvoidingView } from 'react-native';
import colors from '../config/colors';
import AppButton from '../components/AppButton';
import AppTextInput from '../components/AppTextInput';
class EditScreen extends Component {
constructor(props) {
super(props);
this.state = { ...props.item };
}
render() {
const { onEdit, onClose } = this.props;
const { title, des, image } = this.state;
return (
<KeyboardAvoidingView
behavior="position"
keyboardVerticalOffset={Platform.OS === 'ios' ? 0 : 100}>
<Image style={styles.image} source={image} />
<View style={styles.detailContainer}>
<AppTextInput
value={title}
onChangeText={text => this.setState({ title: text })}
/>
<AppTextInput
value={des}
onChangeText={text => this.setState({ des: text })}
/>
</View>
<AppButton text="Save" onPress={() => onEdit(this.state)} />
</KeyboardAvoidingView>
);
}
}
export default EditScreen;
onEdit
onEdit = data => {
const newPosts = this.state.post.map(item => {
if(item.key === data.key) return data;
else return item;
})
this.setState({ post: newPosts, editMode: false });
};
Only the direct children of a navigator can access
this.props.navigation
If you want to access that inside the edit screen you can pass it from the Home screen as a prop. Like so:
return <EditScreen item={item} onEdit={this.onEdit} navigation={this.props.navigation} />;
But i don't think you need to go back because you are still on the Home page and just rendering the EditScreen within it. So just changing the state to have editMode: false should be enough

React Native - cannot import image from path

I have the following basic react native code:
import React from 'react';
import {StyleSheet, View, Image} from 'react-native';
//images
import login_blueGirl from './assets/images/login_blueGirl.png';
const App = () => {
return (
<>
<View style={styles.container}>
<Image source={login_blueGirl}></Image>
</View>
</>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'column'
}
});
export default App;
I'm getting a Cannot find module './assets/images/login_blueGirl.png'. When I type ./ VSCode give me however the autocomplete option:
Any clue on why this is happening?
That's not quite how you're supposed to be importing images, use require instead.
const App = () => {
return (
<View style={styles.container}>
<Image source={require("./assets/images/login_blueGirl.png")} />
</View>
);
};
You can specify the width and height of the image to display it, do this:
const App = () => {
return (
<View style={styles.container}>
<Image style={{ width: 100, height: 80 }} source={require("./assets/images/login_blueGirl.png")}></Image>
</View>
);
};
or
const styles = StyleSheet.create({
imgStyle: {
width: 50,
height: 50,
}
});
const App = () => {
return (
<View style={styles.container}>
<Image style={styles.imgStyle} source={require("./assets/images/login_blueGirl.png")}></Image>
</View>
);
};
To import a static file like a .png file, you can declare
const blueGirl = require("assets/images/login_blueGirl.png");
Then you can use it in an Image component
<Image style={styles.image} source={blueGirl} />
Also the image is used as a self closing tag you don't have to add another </Image> tag.
In order to fully understand how tags and syntax work always check out the official documentation
React Native API

Single instance of component react native

I want to make a component where it renders a modal.
This component should have states{Key(integer),ImageLink(string),Visible(bool)}.
I am using flatlist. I want to render the component's modal on flatlist parent but component. States changes upon touch on flatlist child.
For example:
Modal Component which means to be single instance
import React from "react";
import {
View,
Modal,
Text,
StyleSheet,
TouchableHighlight,
Platform
} from "react-native";
export default class MySingleInstanceModal extend Component{
constructor(props) {
super(props);
this.state = {
Visiable: props.Visiable, \\Bool For turning Modal On or Off
ImageLink: props.ImageLink, \\String Image Online Link
Key: props.PostKey,\\integer Key
};
}
NextImage = (Current,Link )=> {
this.setState({ ImageLink: Link,Key:Current+1 });
};
ToggleMeOff = () => {
this.setState({ TurnMeOn: false });
};
ToggleMeOn = (MyKey,MyLink) => {
this.setState({ TurnMeOn: true,ImageLink: MyLink,Key:MyKey });
};
PrevImage = (Current,Link )=> {
this.setState({ ImageLink: Link,Key:Current-1 });
};
render() {
return (
<View>
<Modal
animationType="slide"
transparent={false}
visible={this.state.TurnMeOn}
>
<View style={{ marginTop: 22 }}>
<View>
<Text>Hello World!</Text>
<TouchableHighlight onPress={this.ToggleMeOff}>
<Text>Hide Modal</Text>
</TouchableHighlight>
<Image
source={{ uri: this.state.ImageLink }}
resizeMethod={"resize"}/>
</View>
</View>
</Modal>
</View>
);
}
}
Calling In Flatlist Parent:
render() {
return (
<View style={Style1.container}>
<MySingleInstanceModal/> // Here I want to call render
<FlatList
data={data}
initialNumToRender={4}
keyExtractor={this._keyExtractor}
renderItem={this._renderItem}
onEndReached={this._reachedEnd}
refreshing={isRefreshing}
onEndReachedThreshold={0.5}
onRefresh={this._refreshdata}
ListFooterComponent={this.renderFooter}
/>
</view>)
}
And want to change states of MySingleInstanceModal in flatlist items(flatlist child)
somewhere in the rendering of flatlist child item
render(){
return (
...
<TouchableHighlight onPress={() =>
MySingleInstanceModal.ToggleMeOn(this.state.Link,this.state.Key)}>
<Text>Open Modal For Me</Text>
</TouchableHighlight>
...
)
}
Which means component will render at parent but its states will be controlled by the child(Every flatlist item)

Create rows in React Native

i want to create rows for images,which recieve from _find function.This function already seperated array to subarrays,which number equals number of rows,how i can render rows with data from _find?Dont purpose ready solutions such as react-native-easy-grid,i want to do it without another libs,and can i scroll items if i use this way?
import React, { Component } from 'react';
import { AppRegistry, Text, TextInput, View,StyleSheet,Button,Image,ScrollView,Dimensions,ListView } from 'react-native';
import Grid from './GridBuilder.js';
const regUrl = /(src=")?(https:\/\/\S{2,500})(")/gm;
var IMAGES_PER_ROW = 3;
let app1;
export default class inputText extends Component {
constructor(props) {
super(props);
app1 = this;
this.state = {
text: null,
findEvent:false,
im_p_r:3,
items:{},
};
}
render() {
return (
<View style={{margin: 20}}>
<TextInput
style = {styles.searchInput}
placeholder="Type here to search"
onChangeText={(text) => this.setState({text})}
/>
<Button
onPress={() => this._find(this.state.text)}s
title='Find'
color="#841584"
accessibilityLabel="on"
/>
{this.state.findEvent && <DisplayImage />}
</View>
);
}
_find(searchText){
fetch('https://www.googleapis.com/customsearch/v1?key=AIzaSyAfcN3jfimFxHxpHNjhHOSuuY8dm5YZnqQ&cx=007223195539364418542:lcqjo0djp7k&num=10&q='+ searchText+'&searchType=image')
.then((resp) => resp.json())
.then(function(data) {
let s = data.items;
let SIZE = IMAGES_PER_ROW;
let res = s.reduce((p,c)=>{
if(p[p.length-1].length == SIZE){
p.link.push([]);
}
p[p.length-1].push(c);
return p.link;
}, [[]])
app1.setState({items:res,findEvent:true});
})
}
}
export class DisplayImage extends Component {
render(){
return(
<View style={styles.container}>
{app1.state.items.map((item,index) => <View style={styles.row} ><Image style={[styles.image,styles.box]} source={{uri:item.link}} key={index} /></View>)}
</View>
)
}
}
const styles = StyleSheet.create({
searchInput:{
fontSize:20,
paddingTop:20,
paddingBottom:20
},
image:{
paddingTop:20,
width:100,
height:100,
},
row: {
flex: 1,
flexWrap: 'wrap',
flexDirection: 'row',
justifyContent: 'space-between'
},
box: {
flex: 1,
height: 100,
width:100,
backgroundColor: '#333',
},
})
AppRegistry.registerComponent('inputText', () => inputText);
AppRegistry.registerComponent('DisplayImage', () => DisplayImage);
You can use FlatList from React Native.
{this.state.findEvent && <FlatList
data={this.state.items}
renderItem={({ item }) => this.renderItem(item)}
/>}
FlatList receive as data the list of elements you want to render, in this case the data returned from the find function.
And then define the renderItem function like:
renderItem(item) {
return (
<View style={styles.row} >
<Image
style={[styles.image,styles.box]}
source={{uri:item.link}} key={index}
/>
</View>
);
}
This function is in charge of rendering the list of images, each image as a row as you want.
FlatList is really useful and makes lists rendering easier. You get the scroll by default and you can also render separators, have a pull to refresh, etc. Take a look to the FlatList doc to see all properties available.
Here is working example of Flat list by which you can get images in the row
https://snack.expo.io/SJDoljDg7
FlatList is the way to go but I suspect the spec has changed since the original accepted answer. You must now provide a key extractor, here is an example of what worked for me:
const listItems = [
{
"id": 0.7967679550647925,
"name": "Hcsrhjkh",
},
{
"id": 0.3212834674770011,
"name": "Phvdgbb",
},
{
"id": 0.30092504022778455,
"name": "Hnvdghbh",
},
]
...
{listItems.length < 1 ? (
<Text style={{ fontSize: 30 }}>Your list is empty.</Text>
) : (
<FlatList
data={listItems}
renderItem={({item}) => <ListItem item={item} />}
keyExtractor={(item) => item.id.toString()}
/>
)}
As you can might have found, the keyExtractor expects a string so I've coerced the 'id' which is a number to a string.

Programmatically add a component in React Native

Suppose I have a simple React Native app like so:
'use strict';
var React = require('react-native');
var {
AppRegistry,
Text,
TouchableHighlight,
View,
} = React;
var ReactProject = React.createClass({
_onPressOut: function() {
// What do we do here?
},
render() {
return (
<View>
<Text>This text should be before</Text>
<Text>This text should be after</Text>
<TouchableHighlight onPressOut={this._onPressOut}>
<Text>Tap Me</Text>
</TouchableHighlight>
</View>
);
}
});
AppRegistry.registerComponent('ReactProject', () => ReactProject);
How can I dynamically insert a component between the first and second Text tags when the TouchableHighlight is pressed?
Try creating an array and attaching it to the state. You can then push items to the array, and reset the state.
https://rnplay.org/apps/ymjNxQ
'use strict';
var React = require('react-native');
var {
AppRegistry,
StyleSheet,
Text,
View,
TouchableHighlight
} = React;
var index = 0
var SampleApp = React.createClass({
getInitialState(){
return { myArr: [] }
},
_onPressOut() {
let temp = index ++
this.state.myArr.push(temp)
this.setState({
myArr: this.state.myArr
})
},
render() {
let Arr = this.state.myArr.map((a, i) => {
return <View key={i} style={{ height:40, borderBottomWidth:2, borderBottomColor: '#ededed' }}><Text>{ a }</Text></View>
})
return (
<View style={styles.container}>
<Text>First</Text>
{ Arr }
<Text>Second</Text>
<TouchableHighlight style={ styles.button } onPress={ () => this._onPressOut() }>
<Text>Push</Text>
</TouchableHighlight>
</View>
);
}
});
var styles = StyleSheet.create({
container: {
flex: 1,
marginTop:60
},
button: {
height:60,
backgroundColor: '#ededed',
marginTop:10,
justifyContent: 'center',
alignItems: 'center'
}
});
AppRegistry.registerComponent('SampleApp', () => SampleApp);
I've set up a working example here.
In react or react native the way component hide/show or add/remove does not work like in android or iOS. Most of us think there would be the similar stratedgy like
View.hide = true or parentView.addSubView(childView
But the way react native work is completely different. The only way to acheive this kind of functionality is to include your component in your DOM or remove from DOM.
Here in this example I am going set the visibility of text view based on the button click.
enter image description here
The idea behind this task is the create a state variable called state having the initial value set to false when the button click event happens then it value toggles. Now we will use this state variable during the creation of component.
import renderIf from './renderIf'
class fetchsample extends Component {
constructor(){
super();
this.state ={
status:false
}
}
toggleStatus(){
this.setState({
status:!this.state.status
});
console.log('toggle button handler: '+ this.state.status);
}
render() {
return (
<View style={styles.container}>
{renderIf(this.state.status)(
<Text style={styles.welcome}>
I am dynamic text View
</Text>
)}
<TouchableHighlight onPress={()=>this.toggleStatus()}>
<Text> touchme </Text>
</TouchableHighlight>
</View>
);
}
}
the only one thing to notice in this snippet is renderIf which is actually a function which will return the component passed to it based on the boolean value passed to it.
renderIf(predicate)(element).
renderif.js
'use strict';
const isFunction = input => typeof input === 'function';
export default predicate => elemOrThunk =>
predicate ? (isFunction(elemOrThunk) ? elemOrThunk() : elemOrThunk) : null;
With React components you don't want to think of actions reaching into the DOM and inserting components - you want to think components responding to actions. Theoretically, this component is already composed and ready, it just needs to know if it should be rendered or not:
var ReactProject = React.createClass({
getInitialState() {
// our *state* dictates what the component renders
return {
show: false
};
}
_onPressOut: function() {
// update our state to indicate our "maybe" element show be shown
this.setState({show: !this.state.show});
},
maybeRenderElement() {
if (this.state.show) {
// depending on our state, our conditional component may be part of the tree
return (
<Text>Yay!</Text>
);
}
return null;
}
render() {
return (
<View>
<Text>This text should be before</Text>
{this.maybeRenderElement()}
<Text>This text should be after</Text>
<TouchableHighlight onPressOut={this._onPressOut}>
<Text>Tap Me</Text>
</TouchableHighlight>
</View>
);
}
});
I've also made a helper that makes it easy to conditionally render things, render-if
renderIf(this.state.show)(
<Text>Yay</Text>
)
ECMA6 Syntax
import React, { Component } from 'react';
import {
View,
Text,
StyleSheet,
TextInput,
TouchableOpacity,
TouchableHighlight
} from 'react-native';
export default class fourD extends Component {
constructor(props) {
super(props);
let ele1 = (
<View key={1}>
<Text>Element {1}</Text>
<TouchableOpacity onPress={ () => this._add() }>
<Text>Add</Text>
</TouchableOpacity>
</View>
);
this.state = {
ele: [],
key: 1
}
this.state.ele.push(ele1);
}
_add(){
let key = this.state.key + 1;
let ele2 = (
<View key={key}>
<Text>Element {key}</Text>
<TouchableOpacity onPress={ () => this._add() }>
<Text>Add</Text>
</TouchableOpacity>
</View>
);
let ele = this.state.ele;
ele.push(ele2);
this.setState({ ele: ele,key : key})
}
render() {
return (
<View style={styles.container}>
<Text>This text should be before</Text>
{ this.state.ele }
<Text>This text should be after</Text>
<TouchableHighlight onPressOut={ () => this._add() }>
<Text>Tap Me</Text>
</TouchableHighlight>
</View>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "white",
}
})

Categories