Odd react-native issue with rendering - react-native

I'm currently trying to learn react-native and running into a problem after a tutorial. I followed the PropertyFinder tutorial on Ray Wenderlich's site, which went fine.
Breaking away now to start something on my own, I can't seem to get a page to render - and I keep running into the same exception which may be causing the page not to render (but I'm not entirely sure).
Here is the main app page, which is simply the navigator:
'use strict';
var React = require('react-native');
var WelcomePage = require('./WelcomePage');
var {
AppRegistry,
StyleSheet,
Text,
View,
} = React;
var MyApp = React.createClass({
render: function() {
return (
<React.NavigatorIOS style={styles.container}
initialRoute={{
title: 'Welcome',
component: WelcomePage
}}/>
);
}
});
var styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
}
});
AppRegistry.registerComponent('MyApp', () => MyApp);
And here's the welcome page:
'use strict';
var React = require('react-native');
var {
StyleSheet,
Text,
View,
Component
} = React;
var styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF'
},
textTitle: {
color: 'black',
fontSize: 35,
textAlign: 'center'
},
textSubs: {
color: 'black',
fontSize: 25,
textAlign: 'center'
}
});
class WelcomePage extends Component {
render() {
console.log('About to render welcome page');
return (
<View style={styles.container}>
<Text style={styles.textTitle}>
Welcome to MyApp!
</Text>
<Text style={styles.textSubs}>
Good Choice for an App
</Text>
<Text style={styles.textSubs}>
Going to start with setting up the App
</Text>
<Text style={styles.textSubs}>
Are you ready?
</Text>
</View>
);
}
}
module.exports = WelcomePage;
Now, the console logging comes out correctly with 'About to render welcome page', however the result I get is just a blank white window. If I use the chrome debugger, I do get an exception if a chose to Pause on Exceptions. The code snippet it pauses on is this:
/**
* Given a constructor can we call it without `new`?
*
* #param {function} Collection
*/
function isCallableWithoutNew(Collection) {
try {
Collection(); // <<<--- Here's where the exception seems to happen
} catch (e) {
return false;
}
return true;
}
If I go back to the tutorial project, it works just fine.
The only difference I can see is that when I initialized the tutorial project, the Animation library I pulled in did not have an 'Experimental' version (RCTAnimation), but with the new project I tried to start above, I have to use the Experimental version if I want it to work. Really though, I only tested that early on and am not pulling it in any longer (I don't need it yet).
I've also tried playing around a bit with the styles, but get the same result - and the same exception occurring.
Exception stack chrome shows is:
"TypeError: Constructor Map requires 'new'
at Map (native)
at isCallableWithoutNew (http://localhost:8081/index.ios.bundle:15407:5)
at shouldPolyfillES6Collection (http://localhost:8081/index.ios.bundle:15378:5)
at http://localhost:8081/index.ios.bundle:14500:8
at http://localhost:8081/index.ios.bundle:15095:3
at require (http://localhost:8081/index.ios.bundle:245:25)
at http://localhost:8081/index.ios.bundle:14288:11
at require (http://localhost:8081/index.ios.bundle:245:25)
at http://localhost:8081/index.ios.bundle:14131:11
at require (http://localhost:8081/index.ios.bundle:245:25)"
I want to say that looks like an API version issue or something?
Am I missing something obvious here?
Thanks for any help.

So this ended up being my styles on the 'index.ios.js' page.
I changed this:
var styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
}
});
To this:
var styles = StyleSheet.create({
container: {
flex: 1
}
});
And the view then rendered.
I guess I need to spend some time on figuring out how these styles layout components...
If anyone knows why the main NavigatorIOS pane would push content too far off to the right to be visible (which is what was happening) if the styles were set as they were originally, please let me know.
The culprits were:
'justifyContent'
'alignItems'
'backgroundColor' of course had no affect on the view rendering (I didn't add it back in but could without issue).

Related

Inheritance In React Native Style Sheets

So in a regular cascading style sheet we can inherit from other styles doing so:
.myStyle .temp {
height: 100px,
width: 80px,
}
My question is:
is there a way for me to do this in react native. I have tried a few different ways but cannot seem to get it to work. Some of the methods in which I have tried are as follows:
// Example One
// Error Thrown: tempStyle is not defined.
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
...tempStyle,
},
tempStyle :{
backgroundColor: 'tomato'
}
});
The following also did not work for me, it did not throw any errors but simply did not work.
I set the style to be the tempStyle and it was basically a blank style sheet which does make sense as it probably points to nothing.
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
tempStyle :{
container :{
backgroundColor: 'tomato'
}
}
});
I know that we can reference multiple styles inside of the style property in a component using brackets.
<View style={[Styles.temp, Styles.tempTwo]} />
Is this the only way to accomplish this?
Your first idea does not work because you are trying to use a style object defined inside the create function of StyleSheet for another style object defined within the same create function. You cannot access them inside the create function.
However, you could define your styles in a plain JS object and then use the spread syntax in order to achieve pretty much the same thing.
Notice that a style is just a JS object after all.
Let us call this file styles.js.
// helper, keep local
const tempStyle = {
backgroundColor: 'tomato'
}
// we only want to use this style
// spread syntax works here
export const container = {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
...tempStyle,
}
export SomeOtherStyle = {
...tempStyle,
}
Then, we can use the above styles as usual.
import { container, SomeOtherStyle } from './styles.js'
...
<View style={[container, someOtherStyle]}></View>
Notice that we can make use of typescript here as well (if you are using it in your project).
// helper, keep local
const tempStyle: ViewStyle = {
backgroundColor: 'tomato'
}
// we only want to use this style
// spread syntax works here
export const container: ViewStyle = {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
...tempStyle,
}
export SomeOtherStyle: ViewStyle = {
...tempStyle,
}
Using typescript, you will have autocompletion and typechecking for your styles. Notice as well that there might be different styles for different types of components (e.g. TextStyle).
you can use the array notation:
<View style={[styles.container, styles.tempStyle]} />

How to display image when using expo-image-picker-multiple

Im using React Native through expo, and my goal is to select multiple images from my android phone and get their data (uri, name, type, etc) I'm following this guide that I found on here
https://www.npmjs.com/package/expo-image-picker-multiple
they show how to install it (and i did) but not how to use it so i'm lost, the only interesting thread that I found about this specificaly way is this one
https://stackoverflow.com/questions/65877578/how-to-select-multiple-images-from-gallery-with-expo-or-expo-image-picker-multip
I did the 1st direction but couldn't find the second file he said. I tried following his directions in hopes something amazing happened, so i'm not sure if that the answer that I'm looking for.
This is my code
import { StyleSheet, Text, View } from 'react-native';
import { ImageBrowser } from 'expo-image-picker-multiple';
export default function App() {
return (
<View style={styles.container}>
<ImageBrowser max={4} onChange={(num, onSubmit) => {
}}
callback={(callback) => {
}}
/>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
See that ImageBrowser compenent? the num arg shows the number of photos selected, that's the only thing I know, What I see on my phone is my gallery and I can select 4 images but Can't do anything else, help?

React native Responsive layout in Functional component

Below is the basic code for Responsive layout using npm package(react-native-responsive-screen). This is working fine as expected in Class component. But, I want to change the below code to Functional component. I have almost changed everything. Initially no error when i load the app in portrait/landscape mode. Once i change it to landscape/portrait, it will come up with some error.
Here is the link of Original source. https://github.com/marudy/react-native-responsive-screen/blob/master/examples/responsive-screen-orientation-change/README.md
import React, { useEffect, useState } from 'react';
import { StyleSheet, Dimensions } from 'react-native';
import { Container, View, Button, Text} from "native-base";
import {widthPercentageToDP as wp,
heightPercentageToDP as hp,
listenOrientationChange as lor,
removeOrientationListener as rol } from 'react-native-responsive-screen';
const Responsive = () =>
{
useEffect( () =>
{
lor();
return () => rol()
},[])
const styles = StyleSheet.create({
container: { flex: 1, alignItems: 'center', justifyContent:'center' },
title: {
backgroundColor: 'gray',
height: hp('10%'),
width: wp('80%'),
alignItems: 'center',
justifyContent:'center',
marginVertical: wp('10%'),
},
myText: {
textAlign:'center',
color:'white',
fontSize: hp('5%') // End result looks like the provided UI mockup
},
buttonStyle:
{
height: hp('8%'), // 70% of height device screen
width: wp('30%'),
marginHorizontal: wp('10%'),
},
buttonContainer:
{
flexDirection:'row',
marginBottom: wp('10%'),
},
paraContainer:
{
width: wp('80%'),
},
paraText:
{
textAlign:'justify'
}
});
return (
<Container>
<View style={styles.container}>
<View style={styles.title}>
<Text style={styles.myText}>Screen title with 50% width</Text>
</View>
<View style={styles.buttonContainer}>
<Button success style={styles.buttonStyle}><Text>Button 1</Text></Button>
<Button success style={styles.buttonStyle}><Text>Button 2</Text></Button>
</View>
<View style={styles.paraContainer}>
<Text style={styles.paraText}>
As mentioned in "How to Develop Responsive UIs with React Native" article, this solution is
already in production apps and is tested with a set of Android, iOS emulators of different
screen
specs, in order to verify that we always have the same end result.
</Text>
</View>
</View>
</Container>
);
}
export default Responsive;
Thanks in Advance.
It is not due to your code, it is due to library limitation. Current version of library still does not support functional components.
There is an open issue and PR regarding that open
issue: https://github.com/marudy/react-native-responsive-screen/issues/82
PR: https://github.com/marudy/react-native-responsive-screen/pull/70
If you still want to continue with this library, just use the head of that PR in your package.json and it should work.
"react-native-responsive-screen": "marudy/react-native-responsive-screen#70/head",
Make sure to delete node_module and perform yarn or npm install

Implementing dark mode in React Native sensibly

I'm trying to add dark mode support to my React Native app. I will have a flag in a mobx store mode which will be light or dark as appropriate.
In order to tie this into an existing app, I wanted to, if possible, keep the existing style definitions and only override when needed (rather than rewrite everything to a light and a dark theme).
I came up with a function like the following to return the appropriate styles based on the current mode:
function getStyle(style) {
let ret = [styles[style]];
if (
styles.hasOwnProperty(Store.mode) &&
styles[Store.mode][style] !== "undefined"
) {
ret.push(styles[Store.mode][style]);
}
return ret;
}
The view would be rendered as such:
...
<View style={getStyle("container")}>
<Text style={getStyle("text")}>Some text</Text>
</View>
...
The styles:
const styles = {
dark: {
container: {
backgroundColor: "#000"
},
text: {
color: "#fff"
}
},
container: {
padding: 20,
backgroundColor: "#fff"
},
text: {
fontSize: 18,
color: "#000"
}
};
Now this works, but I'm not sure if it's coming at some performance cost I'm unaware of right now (the use of the function, using a style object instead of StyleSheet.create...), or if there's a much simpler way I can't see for the trees. I'd rather not do a ternary inline on every element either.
I ended up going a slightly different way, in that I'd add extra styles depending on the current mode, e.g.
<View style={[styles.container, theme[Store.mode].container]}>
<Text style={[styles.text, theme[Store.mode].text]}>Some text</Text>
</View>
And then using the theme var to override
const theme = {
light: {},
dark: {
container: {
backgroundColor: "#000"
},
text: {
color: "#fff"
}
}
};
const styles = {
container: {
padding: 20,
backgroundColor: "#fff"
},
text: {
fontSize: 18,
color: "#000"
}
};
I would suggest taking a look at the Context api in ReactJS. It gives a good out of the box solution for maintaining global data around the component tree.
You can use React.createContext() and react-native-paper
This module makes it simple to change the background with just a button. I made a simple example for you.
I made an example link.

Function not filling whole screen

Im trying to make an app for the weather in a certain place in the world given by lat and long. The thing is that when I check the screen the applicaction only shows like 1/5 in the center of the screen with the function executed to show the temperature.
Can't upload pictures because of my reputation. But imagine this is the screen: [----|||----] only the ||| portion shows.
I dont know much about react-native so im just searching and doing whatever somebody else do, i have tried forcing a view style "global" for the class but it seems itdoesnt work if you dont put it inside the render, return section which i cant move, atleast to the places i tried.
Didn't include the code inside the functions.
class WeatherScreen extends React.Component {
state = {
isLoading: true,
temperature: 0,
weatherCondition: null,
error: null
};
componentDidMount() {
...
}
fetchWeather(lat, lon) {
fetch(....
}
render() {
const { isLoading, weatherCondition, temperature } = this.state;
return (
<View style={styles.container}>
{isLoading ? (
<View style={styles.loadingContainer}>
<Text style={styles.loadingText}>Fetching The Weather</Text>
</View>
) : (
<Weather weather={weatherCondition} temperature={temperature}/>
)}
</View>
);
}
}
export default WeatherScreen;
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
Do not apply alignItems and justifyContent to the main screen, it will bring your screen to center. If you want your content in the center then add these properties to children View of main container/View.
Also get screen width and height from react-native dimensions and add them to main container style(height, width).
Try this
import { Dimensions } from 'react-native';
const width = Dimensions.get('window').width;
const height = Dimensions.get('window').height;
class YourClass extends Component {
...your code ...
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
height: height,
width: width
},
});