I am creating a component that animates a group of buttons in an elastic staggered way using react-native-pose. The buttons them selves use pose to animate the pressed state. I have almost got it looking how I want it although I'm not sure I'm doing things correctly.
This is what I want to achhieve...
... However the text looks awful like its got jpg artefacts on it :
App.js
import React, { Component } from 'react';
import styled from 'styled-components';
import posed from 'react-native-pose';
import Button from './src/components/Button';
const ScreenContainer = styled.View({
flex: 1,
padding: 20,
marginTop: 100
});
const Buttons = posed.View({
visible: {
staggerChildren: 100
},
hidden: {
staggerChildren: 100
}
});
export default class App extends Component {
state = {
buttonPose: 'hidden'
};
items = [
{ id: 0, label: 'One' },
{ id: 1, label: 'Two' },
{ id: 2, label: 'Three' }
];
componentDidMount = () => {
this.setState({
buttonPose: 'visible'
});
};
render() {
return (
<ScreenContainer>
<Buttons pose={this.state.buttonPose}>
{this.items.map(item => (
<Button label={item.label} key={item.id} />
))}
</Buttons>
</ScreenContainer>
);
}
}
Button.js
import React, { PureComponent } from 'react';
import { TouchableWithoutFeedback } from 'react-native';
import styled from 'styled-components';
import posed from 'react-native-pose';
const Container = styled(
posed.View({
visible: {
opacity: 1,
x: 0
},
hidden: {
opacity: 0,
x: -100
}
})
)({
marginBottom: 20
});
const Background = styled(
posed.View({
// If I comment out these poses the problem goes away
pressIn: {
scale: 1.1
},
pressOut: {
scale: 1
}
})
)({
padding: 20,
backgroundColor: '#f9415d',
borderRadius: 10
});
const Label = styled.Text({
fontSize: 18,
color: 'white',
textAlign: 'center'
});
export default class Button extends PureComponent {
state = {
buttonPose: 'pressOut'
};
onPressIn = () => {
this.setState({
buttonPose: 'pressIn'
});
};
onPressOut = () => {
this.setState({
buttonPose: 'pressOut'
});
};
componentDidMount = () => {};
render() {
const { onPressIn, onPressOut } = this;
const { buttonPose } = this.state;
const { label } = this.props;
return (
<Container>
<TouchableWithoutFeedback onPressIn={onPressIn} onPressOut={onPressOut}>
<Background pose={buttonPose} withParent={false}>
<Label>{label}</Label>
</Background>
</TouchableWithoutFeedback>
</Container>
);
}
}
Can anyone offer any insight into why the text and also the rounded corners look so artifacted and low res?
Related
Im using Material UI's Button component and would like to conditionally determine the variant of the button. That is, on screens medium and up, the variant should be 'outlined' and when the screen is smaller than medium, the variant type should be none. I am using a class component. I have done my research to see what others have done. I have seen the method of using useMediaQuery method but that would require me to change the component to a functional component. Im not sure if I know if that is a good idea because the component is rather a large one and that means will be a bit confusing to convert. I also tried using a ternary operator like this:
const variantType = theme.breakpoints.down("md") ? '' : 'outline';
<Button variant={variantType}>
Food Pick
</Button>
But this didnt do the job. Is there any other way to accomplish this?
Update: Here is my code after trying to wrap the component but in a functional component but its giving an error:
import { withStyles, withTheme, useTheme } from '#material-ui/core';
import PropTypes from 'prop-types';
import Button from '#material-ui/core/Button';
import Typography from '#material-ui/core/Typography';
import Grid from '#material-ui/core/Grid';
import { PulseLoader } from 'react-spinners';
import Icon from '#material-ui/core/Icon';
import Chip from '#material-ui/core/Chip';
import useMediaQuery from '#material-ui/core/useMediaQuery';
const styles = theme => ({
beta: {
height: '17px',
fontSize: '12px',
marginLeft: '10px'
},
scrollContainer: {
flex: 1,
maxHeight: '400px',
minHeight: '300px',
overflowY: 'auto'
},
progressContainer: {
height: '350px',
},
modalDescription: {
color: theme.palette.text.secondary,
marginTop: '20px',
},
button: {
marginTop: '20px',
marginLeft: '10px',
marginRight: '10px',
},
smartSuggestContainer: {
textAlign: 'right',
paddingRight: '35px',
[theme.breakpoints.down('xs')]: {
display: 'flex',
justifyContent: 'center',
flexDirection: 'row',
margin: '40px 0'
},
},
});
export default function MyComponentWrapper({ ...rest }) {
const theme = useTheme();
const mediumScreen = useMediaQuery(theme.breakpoints.down('md'));
return <FoodDescriptions {...rest} mediumScreen={mediumScreen} />;
}
class FoodDescriptions extends Component {
static PAGE_SIZE = 25;
constructor(props) {
super(props);
this.state = {
showFoodDescriptionsModal: false,
dataLoaded: false,
data: [],
page: 0,
sortBy: 'return',
sortDir: 'desc',
};
}
componentDidMount() {
document.addEventListener('keydown', this.handleKeypress);
}
componentWillUnmount() {
document.removeEventListener('keydown', this.handleKeypress);
}
fetchData = async (page, sortBy, sortDir) => {
const { currentBotId } = this.props;
const offset = page * FoodDescriptions.PAGE_SIZE;
const data = await getFoodDescriptions(currentBotId, sortBy, sortDir, FoodDescriptions.PAGE_SIZE, offset);
this.setState({
dataLoaded: true,
data,
});
};
handleKeypress = (e) => {
const { showSnartConfigsModal } = this.state;
const { key } = e;
if (key === 'Escape' && showSnartConfigsModal) {
this.closeModal();
}
};
applyConfig = (botId, params) => {
const { updateConfig, botConfig, actions } = this.props;
updateConfig({ name: botConfig.name, config: Object.assign(botConfig.config, params) });
this.closeModal();
actions.showNotification({ data: 'Configuration has been applied' });
};
openModal = () => {
const { page, sortBy, sortDir } = this.state;
this.fetchData(page, sortBy, sortDir);
this.setState({
showFoodDescriptionsModal: true,
});
};
closeModal = () => {
this.setState({
showFoodDescriptionsModal: false,
});
};
changePage = (page) => {
const { sortBy, sortDir } = this.state;
this.setState({
page,
dataLoaded: false
}, () => this.fetchData(page, sortBy, sortDir));
};
changeSortBy = (sortBy) => {
/* eslint-disable-next-line prefer-destructuring */
let sortDir = this.state.sortDir;
if (sortBy === this.state.sortBy) {
sortDir = (this.state.sortDir === 'desc') ? 'asc' : 'desc';
}
this.setState({
sortBy,
sortDir,
dataLoaded: false,
}, () => this.fetchData(this.state.page, sortBy, sortDir));
};
renderEmptyState() {
const { classes } = this.props;
return (
<Grid container alignItems="center" justify="center" className={classes.progressContainer}>
<Typography className={classes.noCoinsText}>No configurations found</Typography>
</Grid>
);
}
renderLoader() {
const { classes } = this.props;
return (
<Grid container alignItems="center" justify="center" className={classes.progressContainer}>
<PulseLoader size={6} color="#52B0B0" loading />
</Grid>
);
}
renderTable() {
const { data, page } = this.state;
return (
<StrategiesTable
strategies={data}
onClickCopy={this.applyConfig}
page={page}
changePage={this.changePage}
sortBy={this.changeSortBy} />
);
}
render() {
const {
classes, userFeatures, botConfig, theme
} = this.props;
const { showFoodDescriptionsModal, dataLoaded } = this.state;
if (!botConfig) {
return null;
}
return (
<Fragment>
<div className={classes.smartSuggestContainer}>
<Button
name="discoverConfigs"
variant={theme.breakpoints.down(600) ? '' : 'outlined'}
color="primary"
size="small"
disabled={!userFeatures['smart_suggest_backtests'.toUpperCase()] || botConfig.status.toLowerCase() === STATUSES.RUNNING}
onClick={this.openModal}>
Food Buy
</Button>
</div>
</Fragment>
);
}
}
function mapStateToProps(state) {
return {
userFeatures: state.global.paywall.features,
};
}
function mapDispatchToProps(dispatcher) {
return {
actions: {
...bindActionCreators({
showNotification,
}, dispatcher)
}
};
}
connect(mapStateToProps, mapDispatchToProps)(withTheme()(withStyles(styles)(FoodDescriptions)));
Why don't you just create a functional component using useMediaQuery and returning the responsive Button ?
I have three buttons. When I click one button, it fires Context's memo function to add an item into Context's items. I see that clicking one button re-renders all the three buttons, which is not expected. I need to re-render only the clicked button. Please advice.
CounterContext.js
import { createContext } from "react";
export const CounterContext = createContext(null);
App.js
import React from "react";
import { Text, StyleSheet } from "react-native";
import MyButton from "./MyButton";
import { CounterContext } from "./CounterContext";
function counterReducer(prevState, action) {
switch (action.type) {
case "ADD_ITEM":
let items = [...prevState.items, action.item];
return {
items: items,
count: items.length
};
default:
console.log("No action type");
break;
}
}
const buttons = ["1", "2", "3"];
export default function App() {
const [counterState, counterDispatch] = React.useReducer(counterReducer, {
items: [],
count: 0
});
const counterContext = React.useMemo(
() => ({
addItem: item => {
counterDispatch({
type: "ADD_ITEM",
item: item
});
},
items: counterState.items,
itemsCount: counterState.items.length
}),
[counterState.items]
);
return (
<CounterContext.Provider value={counterContext}>
{buttons.map((button, index) => {
return <MyButton key={index} id={button} />;
})}
<Text style={styles.counter}>{counterContext.itemsCount}</Text>
<Text style={styles.items}>{JSON.stringify(counterContext.items)}</Text>
</CounterContext.Provider>
);
}
const styles = StyleSheet.create({
counter: {
margin: 10,
fontSize: 30
},
items: {
margin: 10,
fontSize: 18
}
});
MyButton.js
import React from "react";
import { TouchableOpacity, Text, StyleSheet } from "react-native";
import { CounterContext } from "./CounterContext";
export default function MyButton(props) {
const { addItem } = React.useContext(CounterContext);
let time = new Date().toLocaleTimeString();
console.log(time + " - Rendering MyButton #" + props.id + " ...");
return (
<TouchableOpacity
style={styles.myButton}
onPress={() => {
addItem({
name: "Item #" + props.id
});
}}
>
<Text>Add</Text>
</TouchableOpacity>
);
}
const styles = StyleSheet.create({
myButton: {
width: 100,
margin: 10,
padding: 10,
textAlign: "center",
borderWidth: 1,
borderColor: "#ccc",
backgroundColor: "#e0e0e0",
borderRadius: 5
}
});
Here is the Codesandbox codes: https://codesandbox.io/s/usecontext-dependency-fpcep?file=/src/App.js
Turns out that I have to split Context into two, one that doesn’t have dependency, only to run the functions, and one that shows any value(s) real-time by adding the dependency. The same with the consumer component(s), take it out as new component and put the useContext in there, so parent component won’t be re-rendered.
Code of Home.js
import React, { Component } from 'react'
import { Text, View, Alert } from 'react-native'
import { Card, Title, Paragraph, Button } from 'react-native-paper';
import Animater from '../component/Animater'
import FontAwesome5 from 'react-native-vector-icons/FontAwesome5';
import { act } from 'react-test-renderer';
const data = [
{
id: 1,
q: "Is you age above 50 or below 10",
uri: 'https://miro.medium.com/max/524/1*Peqrh5C9f4lSNNBiwguxTw.png',
},
{
id: 2,
q: "Do You Visited Forign before 15 March?",
uri: 'https://www.howitworksdaily.com/wp-content/uploads/2015/07/68_1.jpg'
},
...
{
id: 9,
q: "Do you meet any Foreigner or NRI",
uri: 'https://assets3.thrillist.com/v1/image/2079046/size/tmg-article_default_mobile_2x.jpg',
}
]export default class CheckCorona extends Component {
constructor(props){
super(props)
}
ButtonPressed=()=>{
console.log("yess it is working")
}
renderCard(item) {
return (
<View key={item.id}>
<Card>
<Card.Content>
<Title style={{ marginHorizontal: 15, fontSize: 24 }}>Q{item.id}: {item.q}</Title>
<Card.Cover source={{ uri: item.uri }} />
<Card.Actions>
<Button onPress={()=>this.ButtonPressed()} >Yess</Button>
<Button>No</Button>
</Card.Actions>
</Card.Content>
</Card>
</View>
)
}
ShowResult = () => {
return (
<Card>
<Title>Tu Single is thik hai</Title>
</Card>
)
}
render() {
return (
<View>
<Animater
data={data}
renderCard={this.renderCard}
ShowResult={this.ShowResult}
ButtonPressed={this.ButtonPressed}
/>
</View>
)
}
}
and Code of Animate.js is
import React, { Component } from 'react'
import { Text, View, PanResponder, Animated, Dimensions, StyleSheet, Alert } from 'react-native'
const Screen_width = Dimensions.get('window').width;
const Swipe_Limit = Screen_width / 2;
export default class Animater extends Component {
constructor(props) {
super(props)
this.state = {
index: 0
}
const position = new Animated.ValueXY();
this.PanResponder = PanResponder.create({
onStartShouldSetPanResponder: () => true,
onPanResponderMove: (e, gesture) => {
position.setValue({ x: gesture.dx, y: gesture.dy })
},
onPanResponderRelease: (e, gesture) => {
if (gesture.dx > Swipe_Limit) {
this.swipe("right")
} else if (gesture.dx < -Swipe_Limit) {
this.swipe("Left")
} else {
this.resetPosition()
}
}
})
this.position = position
}
DoSwiable = () => {
// const newCheck= 'this.swipe("right")'
if(this.props.ButtonPressed()){
console.log("hello")
}
}
swipe = (direction) => {
const x = direction === 'right' ? Screen_width * 3 : -Screen_width * 3
Animated.timing(this.position, {
toValue: { x: x, y: 0 }
}).start(() => {
this.position.setValue({ x: 0, y: 0 }),
this.setState({
index: this.state.index + 1
})
})
}
resetPosition = () => {
Animated.spring(this.position, {
toValue: { x: 0, y: 0 }
}).start()
}
mycardstyle = () => {
const rotate = this.position.x.interpolate({
inputRange: [-Screen_width, 0, Screen_width],
outputRange: ['-120deg', '0deg', '120deg']
})
return {
...this.position.getLayout(),
transform: [{ rotate: rotate }]
}
}
rendercard = () => {
if (this.state.index >= this.props.data.length) {
return this.props.ShowResult()
}
return this.props.data.map((item, i) => {
if (i < this.state.index) {
return null
}
if (i === this.state.index) {
return (
<Animated.View key={i}
style={[this.mycardstyle(), styles.cardStyle]}
{...this.PanResponder.panHandlers}>
{this.props.renderCard(item)}
</Animated.View>
)
}
return (
<View key={item.id} style={[styles.cardStyle, { top: 5 * (i - this.state.index) }]}>
{this.props.renderCard(item)}
</View>
)
}).reverse()
}
render() {
return (
<View>
{this.rendercard()}
</View>
)
}
}
const styles = StyleSheet.create({
cardStyle: {
position: "absolute",
zIndex: 1,
width: Screen_width
}
})
Actually it is swipeable card I want that when Yes button on Home.js pressed then function on animated.js should run this.swipe("right")
Actually I have used props for the showing the data and so the main screen is Home.js and I have import the Animater.js and pass some function is a props and then I am running the props.
Change
ButtonPressed=()=>{
console.log("yess it is working")
}
to
ButtonPressed=()=>{
console.log("yess it is working");
(new Animater()).swipe("right");
}
Hope this helps you!
I am new at React Native.
I'm working on a code that will change the background color of a box (card) according to the data that I will get from API. I want to check first if the title is like 'Taylor' make background red , if it is 'Fearless' make it green and so on.
Here is the API that I got information from :
http://rallycoding.herokuapp.com/api/music_albums
This is the code divided into several files.
First of them index.js
// Import a library to help to create a component
import React from 'react';
import { Text, AppRegistry, View } from 'react-native';
import Header from './src/components/header.js';
import AlbumList from './src/components/AlbumList.js'
// create a component
const App = () => (
<View>
<Header headerText={'Smart Parking'}/>
<AlbumList />
</View>
);
//render it to the device
AppRegistry.registerComponent('albums2', () => App);
second is AlbumList.js
import React, { Component } from 'react';
import { View } from 'react-native';
import axios from 'axios';
import AlbumDetail from './AlbumDetail.js'
class AlbumList extends Component {
state = { albums: [] };
componentWillMount() {
axios.get('https://rallycoding.herokuapp.com/api/music_albums')
.then(response => this.setState({ albums: response.data }) );
}
renderAlbums() {
return this.state.albums.map(album =>
<AlbumDetail key={album.title} album={album} />
);
}
render() {
return(
<View>
{this.renderAlbums()}
</View>
);
}
}
export default AlbumList;
3rd is AlbumDetail.js
import React from 'react';
import {Text, View} from 'react-native';
import Card from './Card.js'
const AlbumDetail = (props) => {
return(
<Card>
<Text> {props.album.title} </Text>
</Card>
);
};
export default AlbumDetail;
4th is card which I need to change background of it
import React from 'react';
import { View } from 'react-native';
const Card = (props) => {
return (
<View style={styles.containerStyle}>
{props.children}
</View>
);
};
const styles = {
containerStyle:{
borderWidth: 1,
borderRadius: 2,
backgroundColor: '#ddd',
borderBottomWidth: 0,
shadowColor: '#000',
shadowOffset: {width: 0, height:2 },
shadowOpacity: 0.1,
shadowRadius: 2,
elevation: 1,
marginLeft: 5,
marginRight: 5,
marginTop: 10
}
};
export default Card;
last one is header
// Import libraries for making components
import React from 'react';
import { Text, View } from 'react-native';
// make a components
const Header = (props) => {
const { textStyle, viewStyle } = styles;
return(
<View style={viewStyle}>
<Text style={textStyle}>{props.headerText}</Text>
</View>
)
};
const styles ={
viewStyle:{
backgroundColor:'orange',
justifyContent: 'center',
alignItems: 'center',
height: 60,
},
textStyle: {
fontSize: 20
}
};
// make the component to the other part of the app
export default Header;
Basically you need to pass the title of the album as prop to the Card from the AlbumDetails component and then on each Card calculate the color to use and pass it in the style like this:
// AlbumDetails.js component
import React from 'react';
import {Text, View} from 'react-native';
import Card from './Card.js'
const AlbumDetail = (props) => {
return(
<Card title={props.album.title}>
<Text> {props.album.title} </Text>
</Card>
);
};
export default AlbumDetail;
// Card.js component
import React from "react";
import { View } from "react-native";
function calculateColor(title) {
let bgColor;
switch (title) {
case "Taylor":
bgColor = "red";
break;
case "Fearless":
bgColor = "green";
break;
default:
bgColor = "orange";
break;
}
return bgColor;
}
const Card = props => {
const { title } = props;
const backgroundColor = calculateColor(title);
return (
<View style={[styles.containerStyle, { backgroundColor: backgroundColor }]}>
{props.children}
</View>
);
};
const styles = {
containerStyle: {
borderWidth: 1,
borderRadius: 2,
backgroundColor: "#ddd",
borderBottomWidth: 0,
shadowColor: "#000",
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.1,
shadowRadius: 2,
elevation: 1,
marginLeft: 5,
marginRight: 5,
marginTop: 10
}
};
export default Card;
Something like this should work:
Change the AlbumDetail to conditionally render the Card.
const AlbumDetail = props => {
if (props.album.title === 'Taylor') {
return (
<Card style={{ backgroundColor: 'red' }}>
<Text>{props.album.title}</Text>
</Card>
);
} else {
return (
<Card style={{ backgroundColor: 'green' }}>
<Text>{props.album.title}</Text>
</Card>
);
}
};
Override the default style of the card using the passed style prop.
const Card = props => {
return (
<View style={[styles.containerStyle, props.style]}>{props.children}</View>
);
};
accepted answer is great just its a bad habit to do things in render.
i also not sure since every title has a color why wouldnt the server send this in the object props in first place ? :)
class AlbumList extends Component {
state = { albums: [] };
componentDidMount() {
axios.get('https://rallycoding.herokuapp.com/api/music_albums')
.then(response=> Array.isArray(response.data) ? response.data : []) // alittle validation would not hurt :) !
.then(data => this.setState({ albums: data }) );
}
selectHeaderColorForAlbum( album ){
let headerColor = 'red';
// switch(album.title){ ..you logic }
return headerColor;
}
renderAlbums() {
return this.state.albums.map(album =>
<AlbumDetail key={album.title} album={album} color={this.selectHeaderColorForAlbum(album)} />
);
}
render() {
return(
<View>
{this.renderAlbums()}
</View>
);
}
}
const Card = (props) => {
return (
<View style={[styles.containerStyle,{color:props.headerColor}]}>
{props.children}
</View>
);
};
this is easier your logic will render only once.
also notice that react >16.0 depricated componentWillMount, so use DidMount
I have list of items. I am using ListView for it and I need to be able to delete any row by swiping left or right.
Where can I start from here?
If you prefer, follow this guide which uses React Native Swipeout.
Otherwise, here's my SwipeList and SwipeListRow component. I partially use my library Cairn for styling, but it should be easily translated into a normal React Stylesheet if you care to do so:
SwipeList.js
import React from 'react';
import { Text, ListView } from 'react-native';
import styleContext from 'app/style';
const style = styleContext.extend({
listViewSection: {
paddingVertical: 10,
paddingLeft: 15,
backgroundColor: '$greyDefault'
},
'text.listViewSection': {
color: '$greyMid',
fontSize: 16,
marginLeft: 5
}
});
function SwipeList({ dataSource, renderRow }) {
function renderSectionHeader(sectionData, sectionId) {
return (
<View {...style('listViewSection')}>
<Text {...style('text.listViewSection')}>{sectionId.toUpperCase()}</Text>
</View>
);
}
if (!dataSource.rowIdentities.length) {
return (
<Text>No items found.</Text>
);
}
return (
<ListView
dataSource={dataSource}
automaticallyAdjustContentInsets={false}
directionalLockEnabled
keyboardShouldPersistTaps={false}
keyboardDismissMode={'on-drag'}
renderSectionHeader={renderSectionHeader}
renderRow={renderRow} />
);
}
SwipeList.propTypes = {
dataSource: React.PropTypes.shape({
rowIdentities: React.PropTypes.array.isRequired
}).isRequired,
renderRow: React.PropTypes.func.isRequired
};
export default SwipeList;
SwipeListRow.js
import React from 'react';
import {
View,
Text,
ScrollView,
Animated,
Dimensions
} from 'react-native';
import styleContext from 'app/style';
const { width } = Dimensions.get('window');
const style = styleContext.extend({
swipeMessage: {
position: 'absolute',
top: 0,
height: 75,
justifyContent: 'center',
alignItems: 'center'
},
itemContainer: {
width
}
});
const WHITE = 0;
const GREEN = 1;
const AnimatedScrollView = Animated.createAnimatedComponent(ScrollView);
class SwipeListRow extends React.Component {
constructor(props) {
super(props);
this.state = {
color: new Animated.Value(WHITE)
};
}
animateScroll = (e) => {
const threshold = width / 5;
let x = e.nativeEvent.contentOffset.x;
let swiped = null;
x = x * -1;
if (x > -50 && this.swiped !== WHITE) {
swiped = WHITE;
} else if (x < -50 && x > -threshold && this.swiped !== GREEN) {
swiped = GREEN;
}
if (swiped !== null) {
this.swiped = swiped;
Animated.timing(this.state.color, {
toValue: swiped,
duration: 200
}).start();
}
}
takeAction = () => {
if (this.swiped) {
Animated.timing(this.state.color, {
toValue: WHITE,
duration: 200
}).start();
this.props.onSwipe();
}
}
render() {
const { swipeEnabled, swipeMessage, children } = this.props;
const bgColor = this.state.color.interpolate({
inputRange: [
WHITE,
GREEN
],
outputRange: [
'rgb(255, 255, 255)',
'rgb(123, 204, 40)'
]
});
return (
<View>
<AnimatedScrollView
horizontal
directionalLockEnabled
automaticallyAdjustContentInsets={false}
onScroll={this.animateScroll}
scrollEventThrottle={16}
scrollEnabled={swipeEnabled}
onMomentumScrollBegin={this.takeAction}
style={[{ flex: 1 }, { backgroundColor: bgColor }]}>
<View>
<View {...style('itemContainer')}>
{children}
</View>
<View
{...style(
'swipeMessage',
[{ width: width / 5, right: -width / 5 - 20 }]
)}>
<Text {...style('text.bold text.white')}>{swipeMessage}</Text>
</View>
</View>
</AnimatedScrollView>
</View>
);
}
}
SwipeListRow.propTypes = {
children: React.PropTypes.node.isRequired,
onSwipe: React.PropTypes.func.isRequired,
swipeEnabled: React.PropTypes.bool.isRequired,
swipeMessage: React.PropTypes.string.isRequired
};
export default SwipeListRow;
With these components, now all you must do is pass in the required datasource as you would to a normal list view, as described on the ListView component documentation.
<SwipeList
dataSource={dataSource}
renderRow={(item) => (
<SwipeListRow
key={item.id}
swipeMessage={'Delete Item'}
onSwipe={() => deleteItem(item)}
swipeEnabled={true}>
<<< INSERT DISPLAY OF ROW HERE >>>
</SwipeListRow>
)} />
use this one
react-native-swipe-list-view
This works really good and you can scale to anything.