Is there a way how to fix the delay that happens when the user checks the box? - react-native

What I'm trying to do is the user to have the possibility to choose his contact(his contact list) and to save them.
The problem is when the user clicks the checkbox to chose the phone number, it delays 2-3 seconds.
After 2-3 seconds the checkbox is completed.
const onChangeValue = (item) => {
if (itemChecked.includes(item.phoneNumbers[0].digits)) {
itemChecked.splice(itemChecked.indexOf(item.phoneNumbers[0].digits), 1);
} else {
itemChecked.push(item.phoneNumbers[0].digits);
setCheckedBox(true);
}
setItemChecked(itemChecked);
console.log(itemChecked);
// console.log(item);
};
return(
<View>
{itemChecked.includes(item.phoneNumbers[0].digits) === false ? (
<CheckBox
style={{ width: 15, height: 15 }}
right={true}
checked={false}
onPress={() => {
onChangeValue(item, index);
}}
/>
) : (
<CheckBox
style={{ width: 15, height: 15, paddingTop: 8 }}
right={true}
checked={true}
onPress={() => {
onChangeValue(item, index);
}}
/>
)}
</View>
);
How can I solve the delay?

Did you try another ui library for checkbox?
If not, u can check React-Native-Elements and Native-Base

Related

REACT NATIVE How can I highlight an item with a scrollview and increment/decrement the highlighted item?

I am building an 'Initiative Tracker' for home use. My goal is to have the first item at the top of the list highlighted by default and use a counter that keeps track of the turns to highlight the item to correspong with its turn.
Eg. When the '+' button is pressed, the next item should be highlighted and the previous item should return to normal.
I am currently using the map function to display an array. I feel like there should be a way to use the index and a style to achieve what I want, but I've had no luck so far.
Thanks in advance for any help or suggestions!
related code below:
let Encounter1Array = [
{ name: "goblin1", init: 5 },
{ name: "goblin2", init: 8 },
{ name: "goblin3", init: 15 },
{ name: "goblin4", init: 3 },
{ name: "goblin5", init: 9 },
];
function InitiativeTrackerScreen() {
const [encounter, setEncounter] = useState(Encounter1Array);
encounter.sort(function (x, y) {
return y.init - x.init;
});
return (
<KeyboardAvoidingView style={styles.wrapper}>
<ScrollView>
{encounter.map((item, index) => {
return (
<View key={index}>
<TouchableOpacity style={styles.ItemDisplayContainer}>
<View>
<View>
<Text style={{ fontStyle: "italic", fontSize: 16 }}>
{item.name}
</Text>
</View>
<View>
<Text style={{ fontSize: 12 }}>
Initiative: {item.init}
</Text>
</View>
</View>
</TouchableOpacity>
</View>
);
})}
</ScrollView>
</KeyboardAvoidingView>
);
}
You need extra state to keep track of the index of the element you want to highlight. Then you can use a conditional statement to match to right index and switch its style.
const P = ({ list }) => {
const [current, setCurrent] = useState(0);
return list.map((item, i) =>
<View style={i === current ? highlightStyle : style}>
<Button onPress={() => setCurrent(current + 1)}>
{"+"}
</Button>
{item}
</View>
);
};

How to call a method of a component

I am using native-base datepicker and want to call the ShowDatePicker method from outside the component. It owuld be something like this except:
This.DatePicker doesnt exist
I dont know if that method is exposed, or how to reach it..
i think it has something to do with using refs?
Thank you!
<Content>
<Button onPress={this.DatePicker.showDatePicker}>
<DatePicker props}/>
</Content>
DatePicker source code: https://github.com/GeekyAnts/NativeBase/blob/master/src/basic/DatePicker.js
Well, if you have to ref it just like the another answer says, as follows
<Content>
<Button onPress={this.DatePicker.showDatePicker}>
<DatePicker ref={ref => this.DatePicker = ref } {...this.props}/>
</Content>
However this will not fix your issue unless DatePicker component takes a props as ref. In short, even if you do that in your component, you will not have access to the showDatePicker.
Rather trying to do so, you can do this in two way (assuming you are trying to showhide component on button click.
Option 1:
Use a prop showDatePicker which will show hide the component.
For ex,
<Content>
<Button onPress={this.setState({showHide: !this.state.showHide})}>
<DatePicker showDatePicker={this.state.showHide} {...this.props} />
</Content>
then in DatePicker use this prop to do some logic.
Or Option 2,
Use conditional operator to show hide the whole component. w
For ex,
<Content>
<Button onPress={this.setState({showHide: !this.state.showHide})}>
{this.state.showHide && <DatePicker {...this.props} />}
</Content>
Let me know if you wanted to do something else, I will update the answer.
EDIT:
Looking at your code in gist.github.com/fotoflo/13b9dcf2a078ff49abaf7dccd040e179, I figured what you are trying to do.
In short, you trying to show datepicker on click of a button. Unfortunately, this is not possible at the moment looking at Nativebase - how to show datepicker when clicking input? and the documentation https://docs.nativebase.io/Components.html#date-picker-def-headref.
If you really wanna have it, you should think about these possible solution,
Option 1: fork native-base do your manipulation and use the datepicker or even submit the PR to native-base for future use.
Option2: you can use any 3rd party library for eg: https://www.npmjs.com/package/react-native-modal-datetime-picker.
Or my favourite option 3:
import { TouchableOpacity, Text, Modal, View, Platform, DatePickerIOS, DatePickerAndroid } from 'react-native';
state = {
currentDate: date,
showiOSDatePicker: false,
chosenDate: date,
formattedDate
}
showDatePicker = async () => {
if (Platform.OS === 'ios') {
this.setState({
showiOSDatePicker: true
});
} else {
const { chosenDate, currentDate } = this.state;
try {
const {action, year, month, day} = await DatePickerAndroid.open({
date: chosenDate,
maxDate: currentDate
});
if (action !== DatePickerAndroid.dismissedAction) {
const dateSelected = new Date(year, month, day);
const formattedDate = this.getFormattedDate(dateSelected)
this.setState({chosenDate: dateSelected, formattedDate});
console.log(formattedDate)
}
} catch ({code, message}) {
console.warn('Cannot open date picker', message);
}
}
}
render() {
const { showiOSDatePicker } = this.state;
return (
<View>
{showiOSDatePicker &&
<Modal
animationType="fade"
transparent
visible={showiOSDatePicker}
onRequestClose={() => {
Alert.alert('Modal has been closed.');
}}>
<View
style={{
display: 'flex',
flex: 1,
justifyContent: 'center'
}}
>
<View style={{
margin: 22,
backgroundColor: 'rgba(240,240,240,1)'
}}>
<View
style={{
borderBottomColor: 'rgba(87,191,229,1)',
borderBottomWidth: 2,
display: 'flex',
justifyContent: 'center',
height: 70,
paddingRight: 20
}}
>
<Text style={{
color: 'rgba(40,176,226,1)',
fontSize: 20,
paddingLeft: 20
}}>
{formattedDate}
</Text>
</View>
<DatePickerIOS
date={chosenDate}
onDateChange={this.setDate}
maximumDate={currentDate}
mode="date"
/>
<TouchableOpacity
style={{
borderTopColor: 'rgba(220,220,220,1)',
borderTopWidth: 1,
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
height: 50
}}
onPress={this.onCloseDatePicker}
>
<Text>
Done
</Text>
</TouchableOpacity>
</View>
</View>
</Modal>
}
<TouchableOpacity onPress={this.showDatePicker}>
<Text>Show Date</Text>
</TouchableOpacity>
</View>
);
}
Let me know if this make sense, or I will put together a working example in https://snack.expo.io/
Cheers
you have to give a ref to DatePicker
<Content>
<Button onPress={this.DatePicker.showDatePicker}>
<DatePicker ref={ref => this.DatePicker = ref } props}/>
</Content>
I had the same problem and this was my solution:
NativeBase DatePicker:
<DatePicker
defaultDate={new Date(2018, 4, 4)}
minimumDate={new Date(2018, 1, 1)}
maximumDate={new Date(2020, 12, 31)}
locale={"es"}
timeZoneOffsetInMinutes={undefined}
modalTransparent={true}
animationType={"fade"}
androidMode={"default"}
placeHolderText="Select date"
textStyle={{ color: "green" }}
placeHolderTextStyle={{ color: "#d3d3d3" }}
onDateChange={this.setDate.bind(this)}
disabled={false}
ref={c => this._datePicker = (c) }
/>
And with this you can open the datePicker:
<Button onPress={()=>{ this._datePicker.setState({modalVisible:true})}}>
<Text>
showDatePicker
</Text>
</Button>
I hope it helps

How to close swipe item in react-native?

I have this code (get from native-base example) that is working fine. But after click on either sides (right or left), the 'swipe' still open. I know that there is a method called closeRow(), but I don't know how to apply in this case.
Left button is for 'split' item into 2 or more, while right button is to delete current item. What I need is to close all opened rows in this list. Why all? Because in the case of 'delete' function, the current item is deleted in the right way, but the next-one get right button opened (since it's the same 'index' of list, even if the item itself is different).
This is my current code:
<Container style={styles.container}>
<Header>
<Left>
<Button transparent onPress={() => this.props.navigation.goBack()}>
<Icon name="arrow-back" />
</Button>
</Left>
<Body>
<Title>{translate("title", { ...i18n_opt, name })}</Title>
</Body>
</Header>
<Content>
<Modal
isVisible={this.state.visibleModal === true}
animationIn={"slideInLeft"}
animationOut={"slideOutRight"}
>
{this._renderModalContent()}
</Modal>
<View style={styles.line}>
<View style={{ flex: 2 }}>
<Text style={[styles.alignCen, styles.headerTitle]}>
{translate("lap", { ...i18n_opt })}
</Text>
</View>
<View style={{ flex: 10 }}>
<Text style={[styles.alignCen, styles.headerTitle]}>
{translate("time", { ...i18n_opt })}
</Text>
</View>
<View style={{ flex: 3 }}>
<Text
style={[
{ paddingRight: 10 },
styles.alignRig,
styles.headerTitle
]}
>
{translate("diff", { ...i18n_opt })}
</Text>
</View>
</View>
<List
enableEmptySections
dataSource={laps2}
ref={c => {
this.component = c;
}}
renderRow={data => <PersonalRankItem dados={data} />}
renderLeftHiddenRow={data => (
<Button
full
onPress={() => {
this.setState({
...this.state,
visibleModal: true,
cur_tx_id: tx_id,
cur_lap: data.lap
});
}}
style={{
backgroundColor: "#CCC",
flex: 1,
alignItems: "center",
justifyContent: "center",
marginBottom: 6
}}
>
<MaterialCommunityIcons
name="arrow-split-vertical"
size={20}
color="#5e69d9"
/>
</Button>
)}
renderRightHiddenRow={(data, secId, rowId, rowMap) => (
<Button
full
danger
onPress={_ => {
//alert("Delete");
//console.log("Data.lap:",data.lap);
dispatchDeleteLap(tx_id, data.lap, true);
}}
style={{
flex: 1,
alignItems: "center",
justifyContent: "center",
marginBottom: 6
}}
>
<Icon active name="trash" size={20} />
</Button>
)}
leftOpenValue={70}
rightOpenValue={-70}
/>
</Content>
</Container>
Goal
You need to close all the rows, each time one of row side button clicked. The next problem is when item deleted, the next row is opened even the content is different.
How?
All you need is first, collect the ref of each rows and then when the button clicked, trigger the closeRow method of all ref's row. And the important part, make your row key persistent and unique to avoid problem like in your case.
Quick Code Sample
class Screen extends Component {
constructor(props) {
super(props);
this._rowRefs = [];
}
// this is used to collect row ref
collectRowRefs = (ref) => {
this._rowRefs.push(ref);
};
// your render row function
renderRow = (data) => (
// make this row key consistent and unique like Id, do not use index counter as key
<PersonalRankItem key={data.id} dados={data} ref={this.collectRowRefs}/>
);
// When your hidden side button is clicked
onButtonClicked = (data) => {
// do the button normal action
// ....
// close each row
this._rowRefs.forEach((ref) => {
ref.closeRow();
});
};
// this is your hidden side button
renderLeftHiddenRow = () => (
<Button onClick={this.onButtonClicked} />
);
render() {
// Your List in here
return (
<List
renderRow={this.renderRow}
renderLeftHiddenRow={this.renderLeftHiddenRow}
/>
)
}
}

Precalculate component in react native

I have a piece of components which will be rendered after a user click on a button. However, these components involving too many calculation. It takes 3~5 seconds to complete it.
I want to compute it in advance and store into my state.
So I can show it on the fly.
But somehow, the content always returns null to my state.
Any idea?
prepopulateDetail(){
let displayedSources = {}
this.setState({setState: (
<View>
{
[... new Set(this.props.definition)].map(wordDef => {
if (wordDef.content.length >= 0 && displayedSources.hasOwnProperty(wordDef.source) === false) {
displayedSources[wordDef.source] = true
return (
<View style={styles.definitions} key={guid()} i={wordDef.source}>
<Badge containerStyle={{
backgroundColor: PRIMARY_BG,
width: 100,
marginTop: 5,
marginBottom: 5,
borderRadius: 0
}}>
<Text style={{color: 'white'}}>{wordDef.source.toUpperCase()}</Text>
</Badge>
{
wordDef.content.map((content, j) => {
let data = JSON.parse(content)
return this.displayWordDefinition(data)
})
}
</View>
)
}
})
}
</View>
)}, this.showState)
}

Conditional Rendering on Items of Native Base Picker [React Native]

I’m using ‘Native Base’ components for our product and going good with this,
but I’m stuck at one point and it is around putting Items in Nativebase Picker. My code is like this
Render Method code -
render(){
return (
<View style={{marginTop: 20, flexDirection:'row', flexWrap:'wrap', justifyContent:'space-around', alignItems:'center'}}>
<View style={{flex:1, justifyContent:'center', alignItems:'flex-end' }}>
<Button
style={{ backgroundColor: '#6FAF98', }}
onPress={this._showDateTimePicker}
>
<Text>Select Date</Text>
</Button>
</View>
<View style={{flex:1, justifyContent:'center', alignItems:'stretch'}}>
<Picker
style={{borderWidth: 1, borderColor: '#2ac', alignSelf:'stretch'}}
supportedOrientations={['portrait','landscape']}
iosHeader="Select one"
mode="dropdown"
selectedValue={this.state.leaveType}
onValueChange={(value)=>this.setState({leaveType:value,})
//this.onValueChange.bind(this)
}>
<Item label="Full Day" value="leave1" />
{
this.showStartDateFirstHalf() // Here I want to show this picker item on the basis of a condition
}
<Item label="2nd half" value="leave3" />
</Picker>
</View>
<DateTimePicker
isVisible={this.state.isStartDatePickerPickerVisible}
onConfirm={this._handleDatePicked}
onCancel={this._hideDateTimePicker}
mode='date'
/>
</View>
);
}
showStartDateFirstHalf()
{
if(!this.state.isMultipleDays)
{
return(
<Item label="1st Half" value="leave2" />
);
}
}
So, this code is working fine if this.state.isMultipleDays is false, But when this.state.isMultipleDays is true, it means when it is in else part then i'm getting this error -
Cannot read property 'props' of undefined
I think there's an easier answer to this. Instead of creating the separate showStartDateFirstHalf() function try this:
render() {
const pickerItems = [
{
label: 'Full Day',
value: 'leave1',
},
{
label: '1st Half',
value: 'leave2',
},
{
label: '2nd Half',
value: 'leave3',
},
];
const filteredItems = pickerItems.filter(item => {
if (item.value === 'leave2' && this.state.isMultipleDays) {
return false;
}
return true;
});
// The 'return' statement of your render function
return (
...
<Picker ...>
{(() =>
filteredItems.map(item =>
<Item label={item.label} value={item.value} />
)()}
</Picker>
...
);
}
That way, you already have a list of items that is determined before the return statement of the render cycle. Also the use of filter instead of map will not just give you null as the second item if the condition is not met, but will remove the item altogether.