OnChangeText still doesn't work correctly - react-native

I want to limit TextInput to full number and the value must be less than 50. I'm leveraging OnChangeText event to intercept the input value and filter it accordingly. It kind of works but the issue is, it briefly displays the text before erasing it. This is an excerpt of my code -
const [userInputValue, setuserInputValue] = useState('');
let onChangeTextInput = (value) => {
const numericRegex = /^([0-9])+$/
if(numericRegex.test(value) && Number(value) <= 50) {
setuserInputValue(value)
}
}
return (
<TextInput
placeholder='Type full number less than 50'
onChangeText={newValue => onChangeTextInput(newValue)}
value={ userInputValue }
textAlign='center'
keyboardType='numeric'
style={{
width: 250,
marginVertical: 10
}}
/>
When I searched online, I found this issue was reported as bug for react-native 0.54.3 and supposedly fixed in 0.57.1 (Bug Report). I'm on 0.70.5. I'm wondering if there's any work around for this problem.
System - iOS
React-native - 0.70.5

Related

Populte WYSIWYG editor after react native fetch

I am trying to incorporate this WYSIWYG package into my react native project (0.64.3). I built my project with a managed workflow via Expo (~44.0.0).
The problem I am noticing is that the editor will sometimes render with the text from my database and sometimes render without it.
Here is a snippet of the function that retrieves the information from firebase.
const [note, setNote] = useState("");
const getNote = () => {
const myDoc = doc(db,"/users/" + user.uid + "/Destinations/Trip-" + trip.tripID + '/itinerary/' + date);
getDoc(myDoc)
.then(data => {
setNote(data.data()[date]);
}).catch();
}
The above code and the editor component are nested within a large function
export default function ItineraryScreen({route}) {
// functions
return (
<RichEditor
onChange={newText => {
setNote(newText)
}}
scrollEnabled={false}
ref={text}
initialFocus={false}
placeholder={'What are you planning to do this day?'}
initialContentHTML={note}
/>
)
}
Here is what it should look like with the text rendered (screenshot of simulator):
But this is what I get most of the time (screenshot from physical device):
My assumption is that there is a very slight delay between when the data for the text editor is actually available vs. when the editor is being rendered. I believe my simulator renders correctly because it is able to process the getNote() function faster.
what I have tried is using a setTimeOut function to the display of the parent View but it does not address the issue.
What do you recommend?
I believe I have solved the issue. I needed to parse the response better before assigning a value to note and only show the editor and toolbar once a value was established.
Before firebase gets queried, I assigned a null value to note
const [note, setNote] = useState(null);
Below, I will always assign value to note regardless of the outcome.
if(data.data() !== undefined){
setNote(data.data()[date]);
} else {
setNote("");
}
The last step was to only show the editor once note no longer had a null value.
{
note !== null &&
<RichToolbar
style={{backgroundColor:"white", width:"114%", flex:1, position:"absolute", left:0, zIndex:4, bottom: (toolbarVisible) ? keyboardHeight * 1.11 : 0 , marginBottom:-40, display: toolbarVisible ? "flex" : "none"}}
editor={text}
actions={[ actions.undo, actions.setBold, actions.setItalic, actions.setUnderline,actions.insertLink, actions.insertBulletsList, actions.insertOrderedList, actions.keyboard ]}
iconMap={{ [actions.heading1]: ({tintColor}) => (<Text style={[{color: tintColor}]}>H1</Text>), }}
/>
<RichEditor
disabled={disableEditor}
initialFocus={false}
onChange={ descriptionText => { setNote(descriptionText) }}
scrollEnabled={true}
ref={text}
placeholder={'What are you planning to do?'}
initialContentHTML={note}
/>
}
It is working properly.

React Native how to use fast image for expo using cache

I uploaded images to firebase storage and fetching it on the display. It's working fine, but I noticed that it reloads every time changing to other page and the speed is quite slow.
So, after googling I found expo-fast-image (because I'm using expo)
https://www.npmjs.com/package/expo-fast-image
so, after installing it, I'm trying to follow or copy the given an example, but I don't know how to use it properly. Below is my code with expo-fast-image.
Does anyone know how to use it properly?
import ExpoFastImage from 'expo-fast-image';
const CustomListItem = ({id, number, data, coffeeBean, description, image, Order}) => {
const user = auth.currentUser;
const name = user.displayName;
const ImageLoad = (image, id) => (
<View>
<ExpoFastImage
uri= {image}
CacheKey={`cache.${id}`}
/>
</View>
)
return (
<ListItem key={id} bottomDivider onPress={() => {Order({id, number, coffeeBean, description, image})}} >
<ExpoFastImage image={image, id}/>
<Avatar rounded source={{CacheKey: `cache.${id}`}} />
<ListItem.Content >
<ListItem.Title style={{ fontWeight: '800'}}>{id}</ListItem.Title>
<ListItem.Subtitle numberOfLines={1} ellipsizeMode='tail'>
Stock: {number}
</ListItem.Subtitle>
</ListItem.Content>
</ListItem>
)
}
export default CustomListItem
If expo-fast-image uses Image from react-native, images are cached and they are downloaded again only when the url changes. So in your situation, you might be giving different urls to the component which propmts it to download again. Make sure the url is always the same. Even if you add some random string like #some-random-value at the end of url which does nothing. It triggers the download action.

React Native for loop with Array not doing what I expected

I'm trying out some things in React Native for the first time and i'm trying to roll 3 dices (text based for now).
I'm using a for loop to go over an array of the 3 dices. However i'm only seeing one dice text being updated (the 3rd one).
Also when doing some alerts to check what's going on within that for loop, i'm seeing unexpected things? the first alert says 2, the second alert says 1 and then it usually no longer alerts, seldom it also alerts a third time with a 0.
My code so far:
(file: Game.js)
import React from 'react'
import { StyleSheet, Image, Text, View, Button } from 'react-native'
export default class Home extends React.Component {
state = {
dices: [null, null, null],
rollsLeft: 3,
keepDices: [false, false, false],
}
//When this component is mounted (loaded), do some defaults
componentDidMount() {
}
//Roll dices
rollDices = () => {
for(let i = 0; i < 3; i++){
alert('for loop at ' + i);
//Math random to get random number from rolling the dice
randomNumber = Math.floor(Math.random() * 6) + 1;
//Check if the user wanted to keep a dice's value before reassigning a new value
if(this.state.keepDices[i] === false){
//User want to roll this dice, assign new random number to it
//this.setState.dices[i] = randomNumber;
let newDices = [ ...this.state.dices ];
newDices[i] = randomNumber;
this.setState({ dices : newDices });
}
}
//Deduct 1 roll from total
this.setState.rollsLeft--;
//TODO: Check if rolls equals 0, then make player2 active!
}
render() {
return (
<View style={styles.container}>
<Text> {this.state.dices[0]} ONE </Text>
<Text> {this.state.dices[1]} TWO</Text>
<Text> {this.state.dices[2]} THREE</Text>
<Text>Turns left: {this.state.rollsLeft} </Text>
<Button
title="Roll 🎲"
onPress={this.rollDices} />
</View>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center'
},
})
In React Native the setState function is asynchronous.
Meaning that this.setState({ dices : newDices }); can end up setting dices to different values depending on which finishes first.
If you want to control what happens after you use setState, you can call a function after the set is done like this
this.setState({dices: newDices}, () => {
// Do something here.
});
There is some really useful information on calling function after the setState here: Why is setState in reactjs Async instead of Sync?
and some good explanations of how setState in react works and how to get around it here: https://medium.com/#wereHamster/beware-react-setstate-is-asynchronous-ce87ef1a9cf3
Together with DCQ's valuable input for async setStates bundling I also noticed that i'm always resetting the copied dice array within the for loop and thus only saving my last dice correctly.
Next up the for loop was actually counting right from 0 to 2 however the alert boxes don't interrupt the code as i'm used to in the browser therefore it looked a bit off. When doing console.log (which is also cleaner and more correct logging) I noticed things did went right there.

react-native-image-zoom-viewer library not working as per expectation for image zoom in release build

I am using react-native-image-zoom-viewer for zooming of images when images are clicked in a carousal. The image zoom functionality works fine when the app is running in debug mode. But when i am trying to test this same functionality in release mode, it's not working as expectation.
I am passing props for initial view of the image as 300*300 (height*width), that runs fine on debug mode. But in release mode, the same doesn't work and i think new image size becomes 800*800 but i am never passing any-kind of values like that.
I have already tried by passing proper props as suggested by library as per its document. Did some alterations too. But nothing seems working on debug mode
const imageList = [];
for (let i=0; i<images.length; i++){
imageList.push({url:images[i].uri,width:300,height:300});
}
return(
<ImageViewerLib
imageUrls={imageList}
renderIndicator={()=>{}}
loadingRender={()=><Loader isLoader = { true } style = {{height:100,with:100}} />}
renderArrowLeft={()=>
<View style={{padding: 10}} >
<Icon
type = { 'Ionicons' }
name = { 'arrow-round-back' }
/>
</View>
}
renderArrowRight={()=>
<View style={{padding: 10}}>
<Icon
type = { 'Ionicons' }
name = { 'arrow-round-forward' }
/>
</View>
}
backgroundColor="white"
index={imageIndex}
saveToLocalByLongPress={false}
enablePreload={true}
flipThreshold={50}
maxOverflow={300}
/>
);
As you can see in the above code that i am passing fixed image width and height which works smoothly in debug mode.
But when in release mode, this size doesn't work. Initial rendered image is much lager that above provided dimension.

TextInput : when maxLength is full automatically focus next field

I have an issue in my app with TextInput for a bank card numbers digit (error because user not type all number 16 digits).
So I would like to cut CB number on 4 TextInputs and focus automatically on next field after filled the 4 digits. (as already seen it in the web app)
But when I focused the next field, the current became empty, even if the state is correctly set.
Do you have an idea about how can I do that or is it impossible ?
ie. see the onChangeText on this example (exp date actually) :
<TextInput
ref='card_exp_date_mm'
style={[styles.inputTxt, {width: 30, flex: 0}]}
value={this.state.cardExpDateMonth}
keyboardType='numbers-and-punctuation'
placeholder='MM'
returnKeyType='next'
clearTextOnFocus={false}
autoCorrect={false}
placeholderTextColor={Constants.placeholderTextColor}
maxLength={2}
enablesReturnKeyAutomatically={true}
blurOnSubmit={false}
onChangeText={text => {
this.setState({cardExpDateMonth: text})
//console.log('onChangeText', this.refs.card_exp_date_mm)
if(text && text.length == 2){
this.refs.card_exp_date_aa.focus();
}
}}
onSubmitEditing={()=>this.refs.card_exp_date_aa.focus()}/>
you could do something like in this example:
this.refs[nextField].focus()
You should really check this example out, it covers what you are searching for.