I want to make links navigate to a different screen in my messaging app. Is there a way to make TouchableOpacity inline?
Here is a quick workaround, this is not highly optimized but should work in most cases
function createTextLinks(text) {
let texts = text.split(' ');
let comps = texts.map((link) => {
let linking = link.match(/([^\S]|^)(((https?\:\/\/)|(www\.))(\S+))/gi);
if(linking) return <TouchableOpacity onPress={() => Linking.openURL(linking)}>{linking}</TouchableOpacity>
return link
});
//insert space again
comps = comps.map(comp=>[comp," "]);
return comps.flat()
}
Now you can use it like following
<Text>
{
createTextLinks_(
"If you find this interesting, email us at https://www.saachitech.com or contact us at http://stackoverflow.com and we will help you out! "
)}
</Text>
Note
React Native Text have a data detector property which convert a link to hyperlink but itβs only available on Android. Here is the link https://reactnative.dev/docs/text#datadetectortype
Related
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.
I have a simple function to display a playing card in my react native (expo) project. It works when testing locally but not when building for a device (APK, etc). From my understanding it is because the string in require can not be dynamic. If that is the case, what is the best way to handle this issue?
Do I have to do a require for all 52 cards and then pick the appropriate variable for the source of that card? or is there a better way?
export default function Card( { cardID, index, onCardClick }) {
const rankIndex = cardID % 13;
const rank = RANKS[rankIndex];
const suitIndex = cardID / 13 | 0;
const suit = SUIT[suitIndex];
let cardImage = require('../../assets/game/cards/'+rank+suit+'.png');
return (
<TouchableOpacity style={[index && index != 0 && styles.cardMargin]} onPress={() => onCardClick(cardID)}>
<Image style={styles.card} source={cardImage} />
</TouchableOpacity>
);
}
Thank you
do something like this:
const cardImages = {
AceSpades: require('../../assets/game/cards/acespaces.png'),
AceClubs: require('../../assets/game/cards/aceclubs.png'),
// etc..
};
you can generate this array from your filesystem by writing a little node script or create it manually.
metro bundler requires that imports are static.
You should make a function that return all the images as an array and then select the index that of specific image that you want.
I'm building a chat application which is working fine but now I want to implement blue tick feature to check either message has been seen or not. I'm using socket.io and react-native-gifted-chat in this app. I am struggling to find a way to know how to do this. I visit many links but did not get the clear picture. react-native-gifted-chat describes to use renderTicks function for this but I'm unable to understand its implementation.
renderTicks
renderTicks = (message) => {
const {currentMessage, renderTicks, user} = this.props;
if (renderTicks && currentMessage) {
return renderTicks(currentMessage);
}
if (currentMessage && user && currentMessage.user._id !== user._id) {
return null;
}
if (
currentMessage &&
(currentMessage.sent || currentMessage.received || currentMessage.pending)
) {
return (
<View style={styles.content.tickView}>
{!!currentMessage.sent && (
<Text style={[styles.content.tick, this.props.tickStyle]}>β</Text>
)}
{!!currentMessage.received && (
<Text style={[styles.content.tick, this.props.tickStyle]}>β</Text>
)}
{!!currentMessage.pending && (
<Text style={[styles.content.tick, this.props.tickStyle]}>π</Text>
)}
</View>
);
}
return null;
};
GiftedChat
<GiftedChat
..........
renderTicks={(message) => this.renderTicks(message)}
/>
Here currentMessage and renderTicks both are coming undefined.
What I'm doing wrong here, kindly enlighten.
OR
Can anybody help me out with example code of renderTicks.
react-native version = 0.62.2
Thanks in advance.
You need to update the message object from the receivers end, when the receiver opens the chat screen component, you can use a useEffect function that mutates the message object at the server. Like it sets the read property to true. The sockets will automatically notify the sender that the object has changed, and the sender will refetch the chat list, with read property set to true. And gifted chat will show a blue tick.
My task is to filter some array and set it to FlatList.
My filter function is:
updateInvoiceList = (text) => {
let invoiceList = [...this.state.baseInvoiceList];
invoiceList = invoiceList.filter(el => {
return el.name.toLowerCase().includes(text.toLowerCase())
});
this.setState({invoiceList})
}
After filtering, I provide state.invoiceList to FlatList and everything works correctly. But, when I set some symbol which does not exist in my array, for example "!", the function clears the array and it still behaves correctly. When I remove the symbol "!", I get an error screen with:
index=10 count=0
addInArray
ViewGroup.java:5235
addViewInner
ViewGroup.java:5128
addView
ViewGroup.java:4935
addView
ReactViewGroup.java:452
addView
ViewGroup.java:4875
addView
ReactViewManager.java:269
addView
ReactViewManager.java:36
manageChildren
NativeViewHierarchyManager.java:346
execute
UIViewOperationQueue.java:227
run
UIViewOperationQueue.java:917
flushPendingBatches
UIViewOperationQueue.java:1025
access$2600
UIViewOperationQueue.java:46
doFrameGuarded
UIViewOperationQueue.java:1085
doFrame
GuardedFrameCallback.java:29
doFrame
ReactChoreographer.java:166
doFrame
ChoreographerCompat.java:84
run
Choreographer.java:964
doCallbacks
Choreographer.java:790
doFrame
Choreographer.java:721
run
Choreographer.java:951
handleCallback
Handler.java:883
dispatchMessage
Handler.java:100
loop
Looper.java:214
main
ActivityThread.java:7356
invoke
Method.java
run
RuntimeInit.java:492
main
ZygoteInit.java:930
What did I do wrong?
I had the exact same issue with my code, inside a Flatlist and only showing up on Android. I've managed to solve it as follows:
My FlatList had
stickyHeaderIndices={this.state.items[1]}
but apparently the List was loading that stickyHeader ahead of its initialization. From here, the solution consists simply in handling the case in which that item is not initialized yet.
stickyHeaderIndices={this.state.items.length > 0 ? [1] : [0]}
Hope this helps! The solution is pretty straightforward. Debugging it can be a real pain, tho!
On Android, you must not initialise your FlatList stickyHeaderIndices with empty array.
Instead, when your state is not loaded yet, provide FlatList data with some initial data and provide stickyHeaderIndices with [0]
Example code as below
let [data, stickyIndices] = someAPIToGetYourData()
...
...
...
// if your data is not finished loading yet
if (data.length === 0) {
// create not-empty array
data = getInitialNotEmptyData()
// add not-empty index
headerIndexList = [0]
}
return (
<SafeAreaView>
<FlatList
data={data}
stickyHeaderIndices={headerIndexList /* This must not be empty */ }
renderItem={item => renderYourItem(item)}
/>
</SafeAreaView>
)
Hope this help!
I needed kill the FlatList to fix this error, like this:
<View>
{ this.state.data.length > 0 &&
<FlatList
showsVerticalScrollIndicator={false}
refreshing={false}
onRefresh={() => this.onRefresh()}
data={this.state.data}
extraData={this.state}>}
</View>
Hope this helps!
LayoutAnimation causes a similar issue, not only with Flatlist but any kind of lists, check if you are using it in your app and if you have UIManager.setLayoutAnimationEnabledExperimental(true) on your top component, removing it might fix your issue, but will disable the layoutAnimations.
You might find more information here and here
Please improve your function.
updateInvoiceList = (text) => {
let invoiceList = [];
const { baseInvoiceList } = this.state;
if(text){
invoiceList = baseInvoiceList.filter(item => {
return item.name.toLowerCase().includes(text.toLowerCase());
});
}
this.setState({invoiceList});
}
I would like to know if is it possible to redirect to the Youtube app when I press a tab in a DrawerNavigator ?
For example if I have a DrawerNavigator with an item Our Youtube Channel, if I click on it, it will open the youtube App on a specific channel ? Does a specific library exists ?
Thanks !
Try for linking library
and use this code
Linking
.openURL( 'vnd.youtube://user/channel/' + channel_id )
.catch( ... )
For example:
<TouchableOpacity
onPress={() => {
Linking.openURL( 'vnd.youtube://user/channel/' + channel_id );
}}
>
<Text>Youtube channel</Text>
</TouchableOpacity>
This solution is based on the concept of openlink or deeplink.
I use this code to open youtube channel
Linking.canOpenURL('vnd.youtube://channel/' + channelId).then(supported => {
if (supported) {
return Linking.openURL('vnd.youtube://channel/' + channelId);
} else {
return Linking.openURL('https://www.youtube.com/channel/' + channelId);
}
});
I have an another question about youtube. I want to show a playlist when I click on a TouchableOpacity but this time it's in the view. Does it works like deepLinking or ?
In concrete, I have a few images on top, and when i click on one of the image it will show me the playlist that is assigned to this image and a videoPlayer.
Thanks
If you want to open a playlist you can try for
youtube://www.youtube.com/playlist?list=PLgD9br3bze22iMSimpPeQ85CIqLswcklR
or
'vnd.youtube://playlist/list/' + playlist_id
You can use this link to redirect any Youtube channel => vnd.youtube://c/xyzchannel in Linkin.openUrl() from react-native.
For Example:
<TouchableOpacity onPress={()=>Linking.openURL('vnd.youtube://c/TariqMasoodOfficial')}>
<Image
source={require('../../assets/youtube1.jpg')}
style={styles.footerImage}
/>
</TouchableOpacity>
I used youtube Image in TouchableOpacity to click. You can write your channel name right after 'c/' in a link.