Situation: I have a ListView of Switches
Problem: Switches dont change its state when they are pressed, debugging each switch goes to checked but after setValue ends the switch comes back to unchecked. Switches are never being rendered as checked
Here is my code:
import React, { Component } from 'react';
import {
StyleSheet,
View,
Switch,
ListView
} from 'react-native';
export default class FriendListBody extends Component {
constructor(props) {
super(props);
let friends = this.props.friends.map((friend) => {
return {
...friend,
selected: false
}
});
const ds = new ListView.DataSource({ rowHasChanged: (r1, r2) => r1 !== r2 });
this.state = {
datasource: ds.cloneWithRows(friends),
friends
};
this._renderRow= this._renderRow.bind(this);
this._setValue = this._setValue.bind(this);
}
render() {
return (
<View style={styles.container}>
<ListView
dataSource={this.state.datasource}
renderRow={this._renderRow}
style={styles.listView}
enableEmptySections={true}
/>
</View>
);
}
_setValue(id, value) {
let newList = this.state.friends.slice();
let pos = -1;
for (let i = 0; i < this.state.friends.length; i++) {
if (id === this.state.friends[i]._id) {
pos = i;
break;
}
}
newList[pos].selected = value;
this.setState({
friends: newList,
datasource: this.state.datasource.cloneWithRows(newList) }
);
}
_renderRow(rowData) {
return (
<View key={rowData._id} style={{ borderRadius: 10 }}>
<Switch
onValueChange={(value) => this._setValue(rowData._id, value)}
style={{ marginBottom: 10 }}
value={ rowData.selected } />
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#d9d9d9',
},
listView: {
flex: 1,
borderColor: 'grey'
}
});
Somethings that paid my attention is that _renderRow method is called only once, when list is loaded for the first time.
Thanks for helping.
If you want to update listView, create new objects instead of updating the properties of existing objects.
import React, { Component } from 'react';
import {
StyleSheet,
View,
Switch,
ListView
} from 'react-native';
export default class FriendListBody extends Component {
ds = new ListView.DataSource({ rowHasChanged: (r1, r2) => r1 !== r2 });
constructor(props) {
super(props);
let friends = this.props.friends.map((friend) => {
return {
...friend,
selected: false
}
});
this.state = {
datasource: this.ds.cloneWithRows(friends),
friends
};
this._renderRow= this._renderRow.bind(this);
this._setValue = this._setValue.bind(this);
}
render() {
return (
<View style={styles.container}>
<ListView
dataSource={this.state.datasource}
renderRow={this._renderRow}
style={styles.listView}
enableEmptySections={true}
/>
</View>
);
}
_setValue(id, value) {
let newList = this.state.friends.slice();
let pos = -1;
for (let i = 0; i < this.state.friends.length; i++) {
if (id === this.state.friends[i]._id) {
pos = i;
break;
}
}
newList[pos].selected = value;
const datasource = this.ds.cloneWithRows(newList);
this.setState({
friends: newList,
datasource: datasource
);
}
_renderRow(rowData) {
return (
<View key={rowData._id} style={{ borderRadius: 10 }}>
<Switch
onValueChange={(value) => this._setValue(rowData._id, value)}
style={{ marginBottom: 10 }}
value={ rowData.selected } />
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#d9d9d9',
},
listView: {
flex: 1,
borderColor: 'grey'
}
});
Related
I have tried to sychronise-scroll two Flatlist with state but my thought was that scrolling was shaking, lagging and not smooth due to re-rendering. But I tried with referencing React element but it didn't help. The result is the same, scrolling is like a person gotten electrified and shock, that is, shaking.
Code is below:
import * as React from 'react';
import { Text, View, StyleSheet, FlatList, Button } from 'react-native';
import Constants from 'expo-constants';
export default function App() {
const listRefOne = React.useRef();
const listRefTwo = React.useRef();
const handleRef = (listRef, offset) => {
if (listRef === listRefOne) {
listRefTwo.current.scrollToOffset({ animated: true, offset: offset });
console.log('One', offset);
}
if (listRef === listRefTwo) {
listRefOne.current.scrollToOffset({ animated: true, offset: offset });
console.log('Two', offset);
}
};
return (
<View style={styles.container}>
<MyListView listRef={listRefOne} handleRef={handleRef} />
<MyListView listRef={listRefTwo} handleRef={handleRef} />
</View>
);
}
const generateData = () => {
const temp = [];
for (var i = 1; i <= 100; i++) {
temp.push({ id: i, title: `# ${i} Hello` });
}
return temp;
};
const mydata = generateData();
const MyListView = ({ listRef, handleRef }) => {
const handleScroll = (offset) => handleRef(listRef, offset);
return (
<FlatList
ref={(list) => {
listRef.current = list;
}}
style={styles.itemView}
data={mydata}
renderItem={({ item }) => (
<Text style={{ fontSize: 20 }}>{item.title}</Text>
)}
keyExtractor={(item) => item.id}
onScroll={(e) => handleScroll(e.nativeEvent.contentOffset.y)}
/>
);
};
const styles = StyleSheet.create({
container: {
flex: 2,
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
padding: 8,
},
itemView: {
flexGrow: 1,
backgroundColor: '#efefef',
margin: 3,
},
});
Expo Link
<--it shows data.source error-->
import React, { Component } from "react";
import { AppRegistry, StyleSheet, View, Platform, Picker, ActivityIndicator, Button, Alert} from "react-native";
export default class Project extends Component {
constructor(props)
{
super(props);
this.state = {
isLoading: true,
PickerValueHolder : ""
}; }
componentDidMount() {
return fetch("https://facebook.github.io/react-native/movies.json")
.then((response) => response.json())
.then((responseJson) => {
this.setState({
isLoading: false,
dataSource: responseJson
}, function() {
// In this block you can do something with new state.
});
})
.catch((error) => {
console.error(error);
});}
GetPickerSelectedItemValue=()=>{
Alert.alert(this.state.PickerValueHolder);
}
render() {
if (this.state.isLoading) {
return (
<View style={{flex: 1, paddingTop: 20}}>
<ActivityIndicator />
</View>`help needed`
);
}
return (
<View style={styles.MainContainer}>
<Picker
selectedValue={this.state.PickerValueHolder}
onValueChange={(itemValue, itemIndex) => this.setState({PickerValueHolder: itemValue})} >
{ this.state.dataSource.map((item, key)=>(
<Picker.Item label={item.title} value={item.title} key={key} />)
)}
</Picker>
<Button title="Click Here To Get Picker Selected Item Value" onPress={ this.GetPickerSelectedItemValue } />
</View>
);}}
const styles = StyleSheet.create({
MainContainer :{
justifyContent: "center",
flex:1,
margin: 10
}});
import React, { Component } from "react";
import { ListView, Text, StyleSheet, View, ActivityIndicator, Button, Alert} from "react-native";
export default class Project extends Component {
constructor(props)
{
super(props);
this.state = {
isLoading: true,
PickerValueHolder : "",
language: ''
};
}
GetPickerSelectedItemValue(value: string) {
Alert.alert(value);
this.setState({
selected: value
});
}
GetItem (title) {
Alert.alert(title);
}
componentDidMount() {
return fetch('https://facebook.github.io/react-native/movies.json')
.then((response) => response.json())
.then((responseJson) => {
let ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
this.setState({
isLoading: false,
dataSource: ds.cloneWithRows(responseJson['movies']),
}, function() {
// In this block you can do something with new state.
});
})
.catch((error) => {
console.error(error);
});
}
ListViewItemSeparator = () => {
return (
<View
style={{
height: .5,
width: "100%",
backgroundColor: "#000",
}}
/>
);
}
render() {
if (this.state.isLoading) {
return (
<View style={{flex: 1, paddingTop: 20}}>
<ActivityIndicator />
</View>
);
}
return (
<View style={styles.MainContainer}>
<ListView
dataSource={this.state.dataSource}
renderSeparator= {this.ListViewItemSeparator}
renderRow={(rowData) =>
<View style={{flex:1, flexDirection: 'row'}}>
<Text onPress={this.GetItem.bind(this, rowData.title)} style={styles.textViewContainer} >{rowData.title}</Text>
</View>
}
/>
</View>
);
}
}
const styles = StyleSheet.create({
MainContainer :{
justifyContent: "center",
flex:1,
margin: 10
}
});
I am facing 2 issues related to length of my selected photos:
When selecting photos, it lets me to select 5 photos without any issue (it fits my length restriction), however it doesn't save the chosen photos, when I go to the next screen. In another scenario, when I am at the same screen where I choose photos and I choose 6 photos, it selects the 6 photo but the warning popup will appear and say that its currently supports 5, then when I go to next screen its saves the selected photos unlike previously.
If I deselect photos and then try to select another photos (still in my length limit) popup jumps with selection limit and doesn't let me choose photos, when I go to the next screen it saves the changes from previous selection and not from current one.
import React from 'react';
import {
View,
ScrollView,
Image,
Dimensions,
TextInput,
Text,
StatusBar,
TouchableHighlight,
Linking,
Keyboard,
CameraRoll,
KeyboardAvoidingView
} from 'react-native';
import {connect} from 'react-redux';
import {ActionCreators} from '../redux/actions';
import {bindActionCreators} from 'redux';
import Colors from '../constants/Colors';
import api from '../api';
import {
getEmailAddress,
showError,
renderMessageBar,
registerMessageBar,
unregisterMessageBar
} from '../utils/ComponentUtils';
import {
regularHeader,
mainHeader
} from '../utils/Headers';
import {NavigationActions} from 'react-navigation';
import {SelectionLimitDialog} from '../utils/Dialogs';
import {ifIphoneX, isIphoneX} from 'react-native-iphone-x-helper';
import {SafeAreaView} from 'react-navigation';
// specific component imports.
import {List, ListItem} from 'react-native-elements'
import {Button} from 'react-native-elements'
import Loader from '../components/Loader';
import LoaderError from '../components/LoaderError';
import SelectedPhoto from '../components/SelectedPhoto';
class MultiSafeeScreen extends React.Component
{
static navigationOptions = ({navigation}) => {
const {params} = navigation.state;
const isIncome = params ? params.isIncome : false;
const notificationAction = params ? params.notificationAction : () => {};
const isShowBack = params ? params.isShowBack : false;
return mainHeader({
isShowBack: isShowBack,
backAction: () => navigation.goBack(),
notificationAction: () => notificationAction(),
income: isIncome
});
};
constructor(props) {
super(props);
this.selectedPhotos = [];
this.state = {
photos: null,
loader: {
loading: 0,
message: "Loading photos..."
},
selectedPhotos: [],
supportLength: 5
};
this.props.navigation.setParams({notificationAction: this.onNotification, isIncome: this.props.isNewNotifications});
}
UNSAFE_componentWillReceiveProps(newProps) {
if (newProps.isNewNotifications !== this.props.isNewNotifications) {
this.props.navigation.setParams({notificationAction: this.onNotification, isIncome: newProps.isNewNotifications});
}
}
componentDidMount() {
registerMessageBar(this.refs.alert);
let options = {
first: 30,
assetType: 'Photos',
}
CameraRoll.getPhotos(options)
.then(r => {
this.setState({
photos: r.edges,
loader: {
loading: 1,
message: "Loading photos..."
},
});
})
.catch((err) => {
//Error Loading Images
});
StatusBar.setHidden(false);
}
componentWillUnmount() {
unregisterMessageBar();
this.props.setSelectedPhotos(0);
}
onNotification = () => {
this.props.setNewNotifications(false);
this.props.navigation.navigate("Notifications");
}
closeKeyboard = () => {
Keyboard.dismiss();
}
onSelectPhoto = (photo, index) => {
let photos = new Set([...this.selectedPhotos]);
let len = photos.size + 1 ;
console.log('photos')
if (len > this.state.supportLength) {
this.limitDialog.open();
this.setState({selectedPhotos: this.selectedPhotos});
this.props.setSelectedPhotos(len);
}
else {
photos.add(photo);
this.selectedPhotos = Array.from(photos);
}
}
onDeselectPhoto = (photo, index) => {
let photos = new Set([...this.state.selectedPhotos]);
let len = photos.size - 1;
photos.delete(photo);
this.setState({selectedPhotos: Array.from(photos)});
this.props.setSelectedPhotos(len);
}
onNext = () => {
this.props.navigation.navigate("MultiSafeeCreate", {
isShowBack: true,
selected: [...this.state.selectedPhotos]
});
}
renderLoader() {
let {width, height} = Dimensions.get('window');
let photoWidth = width/3;
if (this.state.loader.loading === 0) {
return <Loader style={{justifyContent: 'center', alignItems: 'center'}} message={this.state.loader.message}/>
}
else if (this.state.loader.loading === 2) {
return <LoaderError style={{justifyContent: 'center', alignItems: 'center'}} message={this.state.loader.message}/>
}
// if photos are null do nothing, else if empty show onbording
// if has photos show photos.
if (this.state.photos === null) {
return <Loader style={{justifyContent: 'center', alignItems: 'center'}} message={this.state.loader.message}/>
}
else {
return (
<View style={{width: width, maxHeight: 600}}>
<ScrollView >
<View style={{flexDirection: 'row', width: width, flexWrap: 'wrap',marginBottom:40, justifyContent: 'space-between'}}>
{
this.state.photos.map((p, i) => {
return (
<SelectedPhoto
key={i}
index={i}
style={{
width: photoWidth,
height: photoWidth,
}}
borderColor = "white"
limit={this.state.supportLength}
photo={p}
onSelectPhoto={this.onSelectPhoto}
onDeselectPhoto={this.onDeselectPhoto}
/>
);
})
}
</View>
</ScrollView>
<View style={{ position:'absolute', right:-15, top:475 }}>
<Button
onPress={this.onNext}
containerViewStyle={{width: width}}
backgroundColor={Colors.red}
title='NEXT' />
</View>
</View>
);
}
}
render() {
return (
<View style={{flex: 1, backgroundColor: Colors.white}}>
{this.renderLoader()}
<SelectionLimitDialog ref={(el) => this.limitDialog = el} />
{renderMessageBar()}
</View>
);
}
}
function mapDispatchToProps(dispatch) {
return bindActionCreators(ActionCreators, dispatch);
}
function mapStatesToProps(state) {
return {
isNewNotifications: state.isNewNotifications
};
}
export default connect(mapStatesToProps, mapDispatchToProps)(MultiSafeeScreen);
Teaching myself react native by making a chat app, now when someone clicks on a delete button next to the message (not visible in this code as it's irrelevant), it deletes it from the database but I need to make the changes here in the app.
For this I have set a ref one each of the <Message/> components and I have the ref which matches the ref on the component. But i need to target the actual component node which has that ref.
Is refs the way to go about doing this? If not, what else can I do?
Many thanks
edit: Full code:
import React, { Component } from "react"
import { ListView, View, Text, StyleSheet, TextInput, TouchableHighlight } from "react-native"
import * as firebase from 'firebase';
import Icon from 'react-native-vector-icons/FontAwesome'
import { Hideo } from 'react-native-textinput-effects';
import Message from './Message'
export default class Chat extends Component {
constructor() {
super();
this.ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
this.onSend = this.onSend.bind(this);
this.state = {
messages: this.ds.cloneWithRows([]),
messageContent: '',
};
}
componentWillMount() {
// Get all of the messages from firebase database and push them into "nodes" array which then gets set in the "messages" state above in handleChat.
const chatRef = firebase.database().ref().child('general');
this.messages = [];
chatRef.on('child_added', snap => {
this.messages.push({user: snap.val().user.name,
text: snap.val().text,
messageId: snap.key
})
this.handleChat(this.messages);
}
).bind(this);
// this is what happens when someone removes a comment
chatRef.on('child_removed', snap => {
const messageId = snap.key; // <- This is the key in the database, for example: '-KVZ_zdbJ0HMNz6lEff'
this.removeMessage(messageId);
})
}
removeMessage(messageId){
let messages = this.messages.filter(message => message.messageId !== messageId);
this.handleChat(messages);
}
handleChat(messages) {
this.setState({messages: this.ds.cloneWithRows(messages)})
}
onSend(messages) {
const generalRef = firebase.database().ref().child('general');
const user = firebase.auth().currentUser;
generalRef.push(
{
_id: 1,
text: this.state.messageContent,
createdAt: new Date().getTime(),
user: {
_id: 2,
name: user.displayName,
avatar: 'http://mdepinet.org/wp-content/uploads/person-placeholder.jpg'
}
});
this.setState({messageContent: ''})
}
removeMessage(messageId){
let messages = this.messages.filter(message => message.messageId !== messageId);
this.handleChat(messages);
}
render() {
return (
<View style={{flex: 1, alignItems: 'flex-end'}}>
<ListView
style={{ marginBottom: 60 }}
enableEmptySections={true}
dataSource={this.state.messages}
renderRow={message => <Message name={message.user} text={message.text}/> }/>
<Hideo
style={{position: 'absolute', bottom: 0}}
onChangeText={messageContent => this.setState({messageContent})} value={this.state.messageContent} placeholder="Name"
iconClass={Icon}
iconName={'envelope'}
iconColor={'white'}
iconBackgroundColor={'#222'}
inputStyle={{ color: '#464949' }}
/>
<TouchableHighlight onPress={this.onSend} style={{position: 'absolute', alignItems: 'center', bottom: 10, right: 10, borderRadius: 10, backgroundColor: '#d4af37'}}>
<Text style={{color: 'whitesmoke', fontSize: 20, padding: 5}}>Send</Text>
</TouchableHighlight>
</View>
);
}
}
const styles = StyleSheet.create({
username: {
fontFamily: 'AvenirNext-Bold'
},
comment: {
fontFamily: 'AvenirNext-Regular'
},
bubble: {
flex: 1,
width: 250,
backgroundColor: '#f5f5f5',
margin: 15,
padding: 10,
borderRadius: 20
}
})
Using refs to ListView row items is not a Good idea. As Elmeister told we just need to remove the message elements from array and update the ListView datasource in order to delete a message from ListView.
Here is a sample code which will give you an idea of how you can do the same in your app.
import React, {
Component
} from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
ListView,
TouchableHighlight,
} from 'react-native';
class StackOverflow extends Component {
constructor(props) {
super(props);
const ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
this.messages = this.getMessages();
this.state = {
dataSource: ds.cloneWithRows(this.messages)
};
}
getMessages() {
let arr = [];
for (let i = 0; i < 100; i++) {
arr.push({
user: 'User ' + i,
text: 'This is a sample user message ' + i,
messageId: 'messageId' + i,
});
}
return arr;
}
onDeletePress(messageId) {
this.messages = this.messages.filter(message => message.messageId !== messageId);
this.setState({
dataSource: this.state.dataSource.cloneWithRows(this.messages)
});
}
renderRow(rowData) {
return (
<View style={{padding:8}}>
<Text>{rowData.user}</Text>
<Text>{rowData.text}</Text>
<TouchableHighlight
style={{alignSelf :'flex-end',backgroundColor:'red'}}
onPress={this.onDeletePress.bind(this,rowData.messageId)}>
<Text>Delete</Text>
</TouchableHighlight>
</View>
);
}
render() {
return (
<View style={{flex: 1, paddingTop: 22}}>
<ListView
dataSource={this.state.dataSource}
renderRow={this.renderRow.bind(this)}
/>
</View>
);
}
}
AppRegistry.registerComponent('StackOverflow', () => StackOverflow);
In the above example, We are creating dummy messages and saving them in messages array and updating dataSource with messages.
When onDeletePress is called we pass the messageId to that method, and below line
this.messages = this.messages.filter(message => message.messageId !== messageId);
removes the message from messages array. Then we update the dataSource state which will update the ListView.
In your code probably these changes you will have to make,
Change handleChat
handleChat(messages) {
this.setState({messages: this.ds.cloneWithRows(messages)})
}
Update Chat component like below,
import React, {Component} from "react"
import {ListView, View, Text, StyleSheet, TextInput, TouchableHighlight} from "react-native"
import * as firebase from 'firebase';
import Icon from 'react-native-vector-icons/FontAwesome'
import {Hideo} from 'react-native-textinput-effects';
import Message from './Message'
export default class Chat extends Component {
constructor() {
super();
this.chatRef = firebase.database().ref().child('general');
this.ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
this.onSend = this.onSend.bind(this);
this.state = {
messages: this.ds.cloneWithRows([]),
messageContent: '',
};
}
componentWillMount() {
// Get all of the messages from firebase database and push them into "nodes" array which then gets set in the "messages" state above in updateMessageList.
this._messages = [];
this.chatRef.on('child_added', snap => {
this._messages.push({
user: snap.val().user.name,
text: snap.val().text,
messageId: snap.key
});
this.updateMessageList(this._messages);
}
).bind(this);
// this is what happens when someone removes a comment
this.chatRef.on('child_removed', snap => {
const messageId = snap.key; // <- This is the key in the database, for example: '-KVZ_zdbJ0HMNz6lEff'
this.removeMessage(messageId);
}).bind(this);
}
removeMessage(messageId) {
this._messages = this._messages.filter(message => message.messageId !== messageId);
this.updateMessageList(this._messages);
}
updateMessageList(messages) {
this.setState({messages: this.ds.cloneWithRows(messages)})
}
onSend(messages) {
const user = firebase.auth().currentUser;
this.chatRef.push(
{
_id: 1,
text: this.state.messageContent,
createdAt: new Date().getTime(),
user: {
_id: 2,
name: user.displayName,
avatar: 'http://mdepinet.org/wp-content/uploads/person-placeholder.jpg'
}
});
this.setState({messageContent: ''})
}
render() {
return (
<View style={{flex: 1, alignItems: 'flex-end'}}>
<ListView
style={{ marginBottom: 60 }}
enableEmptySections={true}
dataSource={this.state.messages}
renderRow={message => <Message name={message.user} text={message.text}/> }/>
<Hideo
style={{position: 'absolute', bottom: 0}}
onChangeText={messageContent => this.setState({messageContent})} value={this.state.messageContent}
placeholder="Name"
iconClass={Icon}
iconName={'envelope'}
iconColor={'white'}
iconBackgroundColor={'#222'}
inputStyle={{ color: '#464949' }}
/>
<TouchableHighlight onPress={this.onSend}
style={{position: 'absolute', alignItems: 'center', bottom: 10, right: 10, borderRadius: 10, backgroundColor: '#d4af37'}}>
<Text style={{color: 'whitesmoke', fontSize: 20, padding: 5}}>Send</Text>
</TouchableHighlight>
</View>
);
}
}
const styles = StyleSheet.create({
username: {
fontFamily: 'AvenirNext-Bold'
},
comment: {
fontFamily: 'AvenirNext-Regular'
},
bubble: {
flex: 1,
width: 250,
backgroundColor: '#f5f5f5',
margin: 15,
padding: 10,
borderRadius: 20
}
});
I have a key value array in my state containing booleans indicating the value of my switches.
When I trigger the Switch component, the value is correctly changed in my state but the value of my Switch stays the same. It's like the component is not updated. I did the exact same thing in another project and it is working there.
_changeValue(k) {
switchesValues[k] = !switchesValues[k]
this.setState({
switches: switchesValues
})
}
_renderEventRow(allergiesList) {
var k = allergiesList.key
return (
<View style={{flexDirection: 'row', height: 50, alignItems: 'center', paddingLeft: 10, borderBottomWidth: 0.5, borderColor: 'lightgray'}}>
<Text style={{flex: 1, color: '#5f5f5f'}}>{allergiesList.name}</Text>
<Switch style={{marginRight: 10}} value={this.state.switches[k]} onValueChange={() => this._changeValue(k)}/>
</View>
)
}
My list view :
var ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 != r2})
constructor(props) {
super(props)
this.state = {
ds:[],
dataSource:ds,
switches: []
}
}
componentDidMount() {
this.setState({
dataSource: this.state.dataSource.cloneWithRows(this.state.ds),
})
this.findAllergies()
}
render() {
return(
<ListView
dataSource={this.state.dataSource}
renderRow={(rowData) => { return this._renderEventRow(rowData)}}
/>)}
)
}
findAllergies() {
var that = this
firebase.database().ref("allergies").on("value", (snap) => {
var items = [];
snap.forEach((child) => {
items.push({
name: child.val(),
key: child.key,
})
})
that.setState({
dataSource: that.state.dataSource.cloneWithRows(items),
});
})
}
Hi I have created a sample app to implement your requirement. Have a look at the below code.
import React, {Component} from 'react';
import {
AppRegistry,
Text,
View,
TouchableOpacity,
Switch,
ListView,
} from 'react-native';
var ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 != r2});
export default class AwesomeProject extends Component {
constructor(props) {
super(props)
this.state = {
ds: [],
dataSource: ds,
switches: []
}
}
componentDidMount() {
let allergies = [];
this.switchesValues = [];
for (let i = 0; i <= 5; i++) {
allergies.push({
key: i,
name: 'Name ' + i,
});
this.switchesValues[i] = false;
}
this.setState({
dataSource: this.state.dataSource.cloneWithRows(allergies),
switches: this.switchesValues,
})
}
render() {
return (
<ListView
dataSource={this.state.dataSource}
renderRow={(rowData) => { return this._renderEventRow(rowData)}}
/>);
}
_changeValue(k) {
console.log('Status '+JSON.stringify(this.switchesValues))
this.switchesValues[k] = !this.switchesValues[k];
this.setState({
switches: this.switchesValues,
})
}
_renderEventRow(allergiesList) {
var k = allergiesList.key
return (
<View
style={{flexDirection: 'row', height: 50, alignItems: 'center', paddingLeft: 10, borderBottomWidth: 0.5, borderColor: 'lightgray'}}>
<Text style={{flex: 1, color: '#5f5f5f'}}>{allergiesList.name}</Text>
<Switch style={{marginRight: 10}} value={this.state.switches[k]}
onValueChange={() => this._changeValue(k)}/>
</View>
)
}
}
AppRegistry.registerComponent('AwesomeProject', () => AwesomeProject);