Dont allow view to increase its size depending on contents - react-native

Im new to react-native. I have just created a reusable component of text input as I want.
Im using that reusable component into a view. At one place Im adding reusable component 4 times, and at another place 7 times.
example :
<Textinput
style={styles.textInput}
secureTextEntry={false}
textInputName={'USERNAME'}
showBottomBorder={true}
height={45}
onTextChange={this.onTextChangeUsername}
/>
using above code 7 times in view , causes increase of size of the view.
But I dont want to allow this at it looks ugly on iPhone 4s screen.
So is there any way to disallow that ? Or rather can I give height to reusable component depending upon its parent view's height ?
Like , height={parentView.height/7} ?

I'm not sure exactly how to solve your problem, but if you wanted to add a custom width/height component that depended on the size of the div, you could do something like this with a class function:
resizeGraphs(){
var div = document.getElementsByClassName("yourcontainer")
if (div[0] != undefined){
var divWidth = document.getElementsByClassName("yourcontainer")[0].clientWidth //or .clientHeight
this.setState({
divWidth,
})}}
To explain, this will be called in componentDidMount (I guess you don't have to worry about window resizing). It gets the width of a given class and you can scale your inner elements appropriately as you suggested.
I guess warning flags should be going off if you see direct references to the DOM in react, but I wasn't sure how else to solve this. If anyone has a more "react-y" solution i'd love to see it..

Related

Access standard props when creating custom components without regurgitating them all in the component file

When creating custom components with React Native, is it possible to tweak/access the standard props for the objects within that component without having to define them all inside of the component. I know that's a bit vague, so here's the example: I want to have a TouchableOpacity to use throughout my project with many standard style properties, so I will create a component defining those:
const ButtonStandard = props => {
return(
<TouchableOpacity onPress={props.onPress} style={styles.Buttons}>
<Text style={[styles.ButtonText, {color: props.TextColor}]}>
{props.ButtonText}
</Text>
</TouchableOpacity>
)
}
As you can see, the style of the touchable is defined by styles.Buttons, however the style of the text is defined by styles.ButtonText with the ability to change the text color if I need to through props.TextColor (see Edit below). But as the project grows, there may be a situation where I want the text size larger for one button/touchable. So I add "fontSize: props.TextSize" to the text style. And then another scenario pops up where I want to change the padding on the touchable so I add that.
And now we are back to the question: is it possible to avoid redefining every style property for this component (and any other) by some intrinsic method of overwriting the property where needed? Or is the only solution to keep adding props to cover overwriting the style properties as needed? I understand that at some point there's a line where a second or third or fourth component should be created.
Thanks for your help!
Edit: It seems things weren't even working the way I thought they were. I thought I was setting the font color to black and then giving myself the ability to change it with props.TextColor when using the component, but I realized what's actually happening is it completely ignores the styles."style" (in this case ButtonText) for that property, and sets the value to whatever is defined in the component instance OR the default value if the prop is not used in the component instance. I only thought it was working the way I described above because for text, the default value is black which prevented me from realizing it was ignoring the value in styles.ButtonText when I didn't use props.TextColor. My original question does still stand.
There are a few approaches I have come across (there can be many as well), sharing them here,
If you take any project, as per best practices in regards to UI/UX, you could use only very few types of buttons based on padding, width, color, disability, shape, and everything. You could consider any famous CSS libraries or react-component libraries they provide only a very specific set of button styles, it's because it is always recommended to have same type of button across the applications. Hence you could create a set of button types and let any parent component choose one.
I have also faced an issue, where I had a single text component for the entire project and suddenly new requirements came-up in a such that used text component couldn't handle. This time instead of allowing each property as single prop like instead of padding, margin, color as each one prop, I did expose one prop
called textStyle where parent component can pass the entire TextStyle and that ll be used to override.
for example,
// from parent component
// pass styles only if required to override existing styles
<Button
textStyle={{...anyStyleRelatedToText}}
buttonStyle={{ ...anyStyleRelatedToTouchable }}
/>
// button component
const ButtonStandard = props => {
return(
<TouchableOpacity
onPress={props.onPress}
style={[styles.Buttons, props.buttonStyle]}
>
<Text style={[styles.ButtonText, props.textStyle]}>
{props.ButtonText}
</Text>
</TouchableOpacity>
)
}
Back when I originally asked this question, I did not really know about or understand the spread operator ("..."). It turns out this is the key to achieving my goal. Some code:
style={[
styles.PrimaryStyles, {
backgroundColor: props.ButtonColor,
...props.SecondaryStyles,
}
]}
This is the style declaration for a custom button. Here, I am setting some PrimaryStyles for the button within the component file. These are things I don't expect to change very often at all such as the shadow or alignContent. Then, I include props.XXX for any properties I more or less want to require. What I mean by more or less is, if you don't specify a value for these props, they will default to their default values (if they can). So in this case, the backgroundColor would end up transparent (for iOS at least). And finally, the use of the spreader which allows us to access all of other props available for that component (in this case I was doing a button).
The way React Native implements these properties is in the order they show up. So if PrimaryStyles sets the backgroundColor to red (for no good reason in this situation), and then props.ButtonColor is green, the button will be green. A more applicable example is if PrimaryStyles sets the width to 20% of the screen width, but I have a button I want to be bigger than the others, I can do the following in the instance of that specific button:
<ButtonRectangle>
ButtonColor={ColorScheme.Orange.e}
ButtonText={'Roll Again'}
SecondaryStyles={{
width: Dimensions.get('window').width * 0.5
}}
TextSize={20}
onPress={() => ExerciseGenerator()}
/>
I'm sharing this because it's the best way I figured out how to achieve the functionality in the question. But I'm still a very inexperienced programmer and welcome any feedback on this method.

How is the component view modified when keyboard is showing?

Good morning, this is actually my first question on StackOverflow after a few years in the industry (hope it's not too late!).
I'm working as a side project on a react native app.
I fail to understand how does the view change when the keyboard is up.
When the view shrinks (because the keyboard was shown), views overlap one to another. I want them to still be split.
I have this picture showing what I mean with overlapping views:
I thought it might be something with the paddings/margins, but I removed them all and still the same issue. Now, I know that the input height is defined by an absolute number, and that is what makes it not shrink, so it is bigger than the actual view, that's why it overlaps.
How can I keep my input having a fixed height but also maintaining a margin of separation when the view shrinks ??
Thank you very much!
Edit: I'm editing because I feel like I haven't been able to express my idea of how I need it to work. (Should I delete previous explanation? Keep picture if someone edits and deletes the first explanation).
The initial view with no keyboard has to be like this:
The inputs and buttons have to be at the bottom, the view getting all the height possible.
When opening the keyboard (by clicking on one of the inputs), I want the list to shrink so that the buttons and inputs are still visible and separated by a small margin/padding, and the list to have taken the remaining space (again respecting a small separation between views). The list will still be scrollable (it is a FlatList) when opening the keyboard.
Thank you again and sorry for the misexplanation.
You can try wrapping your content inside a ScrollView instead of a normal View like this:
<ScrollView style={{flex: 1}}>/* your content here */</ScrollView>
So when the keyboard shows up your elements won't overlap since they take the same space but you can scroll to see the elements hidden by the keyboard.
I think you can try something like this:
<View>
<ScrollView>
<KeyboardAvoidingView style={{flex:1}} behavior={Platform.select({ios:"padding", android:null })} keyboardVerticalOffset={Platform.select({ios: 0, android: 500})}>
{/*Your buttons and other elements here...*/}
</KeyboardAvoidingView>
</ScrollView>
<View>
You will also have to import KeyboardAvoidingView and ScrollView from react-native for this.

Create A view with fixed percentage of width in all orientations in React-Native

I want to create a view - that contains a Card - always with '90%' width of the window, whenever the device is vertical or horizontal, or Component is in a parent or not.
What I tried:
1 Using percentage
( width: '90%'):
It works well if I use my card separately on the main view of my screen, but when I use my card on a horizontal ScrollView with other cards I can see many cards, but I want to see only one card before scrolling.
2 Using React.Dimensions
( Dimensions.get('window').width*0.9 with some padding) :
It works perfectly when I use a card separately or even with many inside a scrollView but when I change the orientation of the screen it takes less width of the screen than '90%'.
3 Using flex basis based on this answer
Is there any better way to achieve my goal?
You might wanna look at this package https://github.com/marudy/react-native-responsive-screen
This package doesn't require any orientation change support. It's just one file actually, so you might wanna take a look at that

React Native Custom Button (include two background, two inner component)

How Do I create that Button in React Native?
As above, button component include two part , left is text part, right part include another background color and image.
But, whole button component includes same border radius and gradient.
Does somebody might know how to get to this?
You should wrap two sibling View components with TouchableOpacity component which will handle onPress for the whole button. Position them side by side using flex and set explicit sizes on each. Left element should get borderTopLeftRadius and borderBottomLeftRadius and right should get borderTopRightRadius and borderBottomRightRadius. Border radius is solved separately but it would seem like it's all in one, and for gradient do you mean this inner shadow or something else?
It's because inset shadow does not exist in RN, but it can be faked quite realistically. Read more here: https://github.com/facebook/react-native/issues/2255.
If you really wan't to use gradient, you must use https://github.com/react-native-community/react-native-linear-gradient and position it absolutely over everything and just set it in the background using zIndex property.

How to get the dimensions and position of Native elements in React Native

I am using a framework called react-native-svg to draw SVG elements in a react native view.
My goal is that when I tap on the view (I use a PanResponder on the global view to get that), the element that is the closest to the tap changes.
I have everything that I need, except one thing: I need to be able to know the position of my svg elements, as well as their size, in order to find the one that was the closest to the tap event.
Now, I've tried most of the things available I'd say:
onLayout: those svg elements don't appear to be views and therefore don't call the onLayout callback.
this.refs.elem.measure: same as onLayout, they are not views therefore the measure function is undefined.
UIManager.measure(ReactNative.findNodeHandle(this.refs.elem), callback): returns 0 for all values, apart from the react-native-svg component Svg, but not for all the others: G, Path, Line, etc.
So I was wondering if there was any other solution or if I was doomed. :)
Do I have to change something in react-native-svg that would allow me to find these values or is there any solution ready for me?
Thanks!
I finally had to add some functionalities to react-native-svg so I could get the size of the different elements.
It's not very well done, but I may come back to it for a cleaner solution and submit a PR then.
Thanks.