Including markup for React Native Component Tags inside a Text Element - react-native

I've been trying to include code examples in a style guide for a React Native project and have had trouble finding a way to include the tags without React Native trying to render them itself.
I was hoping to simulate something sort of like Stackoverflow does with it's codeblocks like this:
// Example code for implementing custom button:
<CustomButton
color="primary"
title="Submit"
/>
So my code that breaks looks something like this:
<View>
<Text>
// Example code for implementing custom button:
<CustomButton
color="primary"
title="Submit"
/>
</Text>
</View>
Because React Native tries to render the Button and throws errors.
Is there something similar to HTML's <code> tag inside of React Native or some custom way of achieving the same functionality?

One way to make this work is storing the text as a string in some variable and just rendering that inside the container:
let codeBlock = "<CustButton \n\tcolor=\"primary\" \n\ttitle=\"Placeholder\" \n/>"
<View>
<Text>
// Example code for implementing custom button:
{codeBlock}
</Text>
</View>

with jsx-to-string, you can
<View>
<Text>
{jsxToString(
<CustomButton color="primary" title="Submit" />
)}
</Text>
</View>
This way you can reuse your jsx object easily instead of convert to string manually.

Related

React Native - Modal in Custom Component not showing

I am new to React Native and currently learning on developing a chat app.
I have a Modal that contain Rating UI
Working with these approach
ChatScreen.js
<Modal isVisible={showRateModal} >
<RatingModal />
</Modal>
RatingModal.js
<View style={styles.container}>
<RatingEmojiSection />
<View style={styles.buttonContainer}>
<Button/>
</View>
</View>
Not Working
It works all fine but when I move `Modal` into `RatingModal.js`, the Modal wont be showing anymore. Here is my approach
import { Modal } from 'react-native-paper';
<Modal isVisible={showRateModal} >
<View style={styles.container}>
<RatingEmojiSection />
<View style={styles.buttonContainer}>
<Button/>
</View>
</View>
</Modal>
Anyone have idea why this could happen? PS: the showRateModal state is working fine. I just curious why can't I move the Modal wrapper into RatingModal.js?
I think there are two problems with your current code
First you are rendering two Modals: ChatScreen.js contains a <Modal>, and then you RatingModal code also contains a <Modal> rendering.
Second: from the react-native docs you can see that the required property is not isVisible but visible.
Fixing these two issues should fix your problem.

Accessibility on react native nested text components

From what I understand to create links in inline text the solution is too use nested text components like so (ps i know that using click me as a link is bad style I'm just trying to highlight the main issue)
<Text>
To find out more
<Text onClick={() => console.log('link was pressed')} accessibilityRole="button">
Click me
</Text>
</Text>
The onClick works but the accessibilityRole does not appear to work.

How do you add a Picker in React Native that's going to work for both platforms

I have a bunch of text inputs:
<View style={styles.container}>
<View style={styles.textBoxContainer}>
<TextBoxMA
style={styles.textBox}
placeholder={Labels.USERNAME_PLACEHOLDER}
value={userName}
onChangeText={this.handleTextChange("userName")}
/>
</View>
<View style={styles.textBoxContainer}>
<TextBoxMA
style={styles.textBox}
placeholder={Labels.EMAIL_PLACEHOLDER}
value={email}
onChangeText={this.handleTextChange("email")}
/>
</View>
//here I need to put a Picker, or select element in html terms
</View>
Now, if I put a Picker like this:
<View
style={styles.textBoxContainer}>
<Picker
selectedValue={documentType}
onValueChange={this.handleDocumentTypeChange}
>
<Picker.Item label="ID" value="1" />
<Picker.Item label="Passport" value="212" />
</Picker>
</View>
I get a nice, clean picker in Android. But in iOS I get a picker whose items overlap with the rest of the text boxes and it takes a lot of space. So it destroys all the layout.
I understand that native components corresponding to a dropdown list in the two platforms are different. But how do you handle this?
I've taken a look at AirBnB's app which's been written in React native. In iOS, the view containing the picker slides from the bottom when a corresponding field is clicked (like the Gender field. It looks like a text input but it's not. It just causes the picker to show). And in Android, it's just a modal view with items in the radio button form. They've probably done lots of extra work to achieve that.
Do I need to show picker depending on the platform or is there a built in way to achieve this?
You can use community solutions like
react-native-picker-select
Or
react-native-picker-modal-view
Or
react-native-picker
Or you can build your own solution and do what ever you want you can style and position and even animate your component as you like.

React Native - Default style for elements

Is there a way in React Native to set the style for standard elements without adding a style tag to each and every one? Like for example I want to alter the style for these:
<Text>This is test</Text>
<Text>This is also text</Text>
<Text>And so is this</Text>
As I understand it the only way to say a margin indent is to do this:
<Text style={styles.indentText}>This is test</Text>
<Text style={styles.indentText}>This is also text</Text>
<Text style={styles.indentText}>And so is this</Text>
In ordinary website CSS you can obviously just set some styles for all HTML elements without needing to add a class or ID to them. How is it done in React Native?
You can set an abstraction layer just for it:
IndentedText = React.createClass({
render: () {
<Text style={styles.indentText}>{this.props.text}</Text>
}
})
And then in your other components:
<IndentedText text={"This is a text"} />
<IndentedText text={"This is also a text"} />
<IndentedText text={"And so is this"} />

React Native Touchable is disabling ScrollView

I'm new to React Native, so am probably asking something very obvious, but please help.
I have a view wrapped in a touchable, so that the whole area responds to tapping. Then have a ScrollView nested inside the view. The overall structure is something like this:
<TouchableWithoutFeedback onPress={this.handlePress.bind(this)}>
<View>
<ScrollView>
<Text>Hello, here is a very long text that needs scrolling.</Text>
<ScrollView>
</View>
</TouchableWithoutFeedback>
When this compiles and runs, the tapping is detected, but the scroll view doesn't scroll at all. I made the above code short and simple, but each component has the proper styling and I can see everything rendering fine and the long text is cutoff at the bottom of the ScrollView. Please help.
Thank you!
This is what worked for me:
<TouchableWithoutFeedback onPress={...}>
<View>
<ScrollView>
<View onStartShouldSetResponder={() => true}>
// Scrollable content
</View>
</ScrollView>
</View>
</TouchableWithoutFeedback>
The onStartShouldSetResponder prop stops the touch event propagation towards the TouchableWithoutFeedback element.
I'm using this structure it's working for me:
<TouchableWithoutFeedback onPress={() => {}}>
{other content}
<View onStartShouldSetResponder={() => true}>
<ScrollView>
{scrollable content}
</ScrollView>
</View>
</TouchableWithoutFeedback>
You can have a scrollView or FlatList inside a TouchableWithoutFeedback. Tho you shouldn't but some times you have no other choice to go. Taking a good look at this questions and answer validates that.
close react native modal by clicking on overlay,
how to dismiss modal by tapping screen in react native.
For the Question, The only way you can make it work (atleast that i know of), or the simplest way is to add a TouchableOpacity around Text in your code like this,
<TouchableWithoutFeedback onPress={this.handlePress.bind(this)}>
<View>
<ScrollView>
<TouchableOpacity>
<Text>Hello, here is a very long text that needs scrolling.</Text>
</TouchableOpacity>
<ScrollView>
</View>
</TouchableWithoutFeedback>
Note: TouchableOpacity is a wrapper for making Views respond properly to touches so automatically you can style it the way you would have styled your View Component then set some of its special props to whatever you want e.g activeOpacity etc. Moreso you can use TouchableHighlight it works, but it receives one child element i.e you enclose all your component inside a parent one.
I'm using this structure it's working for me:
<TouchableOpacity>
{other content}
<ScrollView>
<TouchableOpacity activeOpacity={1}>
{scrollable content}
</TouchableOpacity>
</ScrollView>
I found that for my situation the other examples did not work as they disabled the ability to click or disabled the ability to scroll. I instead used:
<FlatList
data={[{key: text1 }, { key: text2 } ...]}
renderItem={({ item }) => (
<TouchableWithoutFeedback onPress={this.onPressContent}>
<Text style={styles.text}>{item.key}</Text>
</TouchableWithoutFeedback>
)}
/>
I happend to need to multiple chunks but you could use single element in the data array for one piece of text.
This let the press event to fire as well as let the text scroll.
Trying to use a ScrollView component inside a TouchableWithoutFeedback component can cause some unexpected behavior because the TouchableWithoutFeedback component is designed to capture user gestures and trigger an action, but the ScrollView component is designed to allow users to scroll through content.Here is what the official docs say
Do not use unless you have a very good reason. All elements that
respond to press should have a visual feedback when touched.
TouchableWithoutFeedback supports only one child. If you wish to have
several child components, wrap them in a View. Importantly,
TouchableWithoutFeedback works by cloning its child and applying
responder props to it. It is therefore required that any intermediary
components pass through those props to the underlying React Native
component.
Thats write , you cannot have a scroll view inside the TouchableWithoutFeedback, it the property of react native that it will disable it, you can instead have your scroll view outside the TouchableWithoutFeedback tab and add the other contents that you want upon the click inside a view tag.
You can also use the Touchable Highlights instead, if the TouchableWithoutFeedback does not works.