RN: Center spinner using flexbox? - react-native

I am trying to get as spinner centered vertically and horizontally (iOS and Android - currently testing on iOS). Here is my JSX
<View>
<Spinner/>
</View>
of course, Spinner is a custom component which is simply this that contains a ActivityIndicator
const Spinner = ({size}) => {
return (
<View style={styles.spinnerStyle}>
<ActivityIndicator/>
</View>
);
};
const styles = {
spinnerStyle: {
flex: 1,
justifyContent : 'center',
alignItems: 'center'
}
}
export {Spinner}
The spinner works but its always at the top of the screen, the spinner contains a VIEW and also the flex items that I think should work. But it doesn't
I also tried add some styles of the the first VIEW that holds the custom component ie..
<View style={....}>
<Spinner/>
</View>
But no joy.

I think you are almost there! The only thing that is missing is to set flex: 1 to the <View> around the <Spinner /> component.
I did create an example on Expo's Sketch. Feel free to have a look at it. Try removing the flex: 1 and add a background color to see how it behaves. Hope it helps!
import React, { Component } from 'react';
import { View, StyleSheet, ActivityIndicator } from 'react-native';
const spinnerStyles = StyleSheet.create({
spinnerStyle: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
});
class Spinner extends Component {
render() {
return (
<View style={spinnerStyles.spinnerStyle}>
<ActivityIndicator size="small" />
</View>
);
}
}
export default class App extends Component {
render() {
return (
<View style={styles.container}>
<Spinner />
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
// backgroundColor: '#4286f4',
},
});

Related

How to change the style of a View, by pressing a nested Button?

I am learning React Native expo, and am trying to change the style (like background color) of a View, by pressing a Button inside it. This is what I have so far:
import { Button, View } from 'react-native';
var styles = {
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: 'blue'
}
};
export default function App() {
return (
<View style={styles.container}>
<Button title='button' onPress={() => styles.A.backgroundColor = 'yellow'} />
</View>
);
}
But when I press the Button, I get the error undefined is not an object (evaluating 'styles.A.backgroundColor = 'yellow'') .
What am I missing? How do I fix this?
With help and guidance from Uger Eren's comments, I was able to figure it out.
import { useState } from 'react';
import { Button, View } from 'react-native';
var styles = {
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
}
};
export default function App() {
var [backgroundColor, setBackgroundColor] = useState('blue')
return (
<View style={[styles.container, {backgroundColor}]}>
<Button title='button' onPress={() => setBackgroundColor('yellow')} />
</View>
);
}
It works!

Invariant Violation: Text strings must be rendered within a <Text> component when several instances of a component is used

I don't why but when I put several same components in a View tag, RN throws a Invariant Violation: Text strings... error.
when I just put one component in my View then it works well
import React from "react";`
import { View, StyleSheet, Text } from "react-native";
export default class Alphabet extends React.Component {
render() {
return (
<View style={styles.container}>
<Text>a</Text>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
width: 50,
height: 50,
borderWidth: 1,
borderColor: "black"
}
});
Alphabets.js
import React, { Component } from "react";
import { StyleSheet, Text, View, Image } from "react-native";
import Alphabet from "../SubComponents/Alphabet";
export default class Alphabets extends React.Component {
render() {
return (
<View style={styles.container}>
<Alphabet /> <Alphabet />
// one <Alphabet/> works as expected
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: "center",
justifyContent: "center"
},
});
EDIT: when I put components each in a new line then it works too.
render() {
return (
<View style={styles.container}>
<Alphabet />
<Alphabet />
</View>
);
}
how can I solve this?
Try removing the space between the two components will remove the error
instead of:
<Alphabet> </Alphabet>
Do something like this
<Alphabet />
<Alphabet />

Open a WebView after a button pressed with reactNative

I am developing a mobile app with React Native. I want to open a WebView after a button pressed. Here is my code, but its not working. The button onPress method is not working.
import React, { Component } from 'react';
import { View, StyleSheet, Button, WebView } from 'react-native';
import { Constants } from 'expo';
export default class webView extends Component {
onNavigationStateChange = navState => {
if (navState.url.indexOf('https://www.google.com') === 0) {
const regex = /#access_token=(.+)/;
const accessToken = navState.url.match(regex)[1];
console.log(accessToken);
}
};
renderContent() {
return (
<WebView
source={{
uri: '',
}}
onNavigationStateChange={this.onNavigationStateChange}
startInLoadingState
scalesPageToFit
javaScriptEnabled
style={{ flex: 1 }}
/>
);
}
render() {
return (
<View style={styles.container}>
<Button
style={styles.paragraph}
title="Login"
onPress={() => this.renderContent()}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
},
});
I tried onPress={this.renderContent()} this also, but it give an exception. What can I do ?
You aren't rendering your WebView in the the render() method of the Component. Just think of render as your DOM of the webpage. You need to provide the component a place in the render component, than you can remove it or add it, see i am calling the renderContent from the render method. So whenever the state variable showWebView is true it will render the WebView You should do something like this:
import React, { Component } from 'react';
import { View, StyleSheet, Button, WebView } from 'react-native';
import { Constants } from 'expo';
export default class webView extends Component {
state={
showWebView: false
}
onNavigationStateChange = navState => {
if (navState.url.indexOf('https://www.google.com') === 0) {
const regex = /#access_token=(.+)/;
const accessToken = navState.url.match(regex)[1];
console.log(accessToken);
}
};
renderContent() {
return (
<WebView
source={{
uri: '',
}}
onNavigationStateChange={this.onNavigationStateChange}
startInLoadingState
scalesPageToFit
javaScriptEnabled
style={{ flex: 1 }}
/>
);
}
render() {
return (
<View style={styles.container}>
{ this.state.showWebView && this.renderContent() }
<Button
style={styles.paragraph}
title="Login"
onPress={() => this.setState({showWebView: true})}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
},
});
I think you must import the following
import { WebView } from 'react-native-webview'
instead of
'react'

react-native webview doesn't appear

For some reason, my react-native webview doesn't show up at all. Nothing shows up after my text field. Here's my code
import React, { Component } from 'react';
import {
View,
Text,
WebView,
} from 'react-native';
export default class Home extends Component {
render() {
return (
<View style={{flexDirection:'column'}}>
<Text>Show webview</Text>
<WebView source={{html:"<html><body style='color:red'>Hello<br/>This is a test</body></html>"}} style={{width:200,height:200,backgroundColor:'blue',marginTop:20}} />
</View>
);
}
}
What am I doing wrong?
Add flex: 1 to your <View /> component.
<View style={{flex: 1, flexDirection:'column'}}>
<Text>Show webview</Text>
<WebView source={{html:"<html><body style='color:red'>Hello<br/>This is a test</body></html>"}} style={{width:200,height:200,backgroundColor:'blue',marginTop:20}} />
</View>
Here's a demo
According to the ReactNative docs as of (Nov 2019) they say this:
Warning Please use thereact-native-community/react-native-webviewfork of this component instead. To reduce the surface area of React Native, <WebView/> is going to be removed from the React Native core. For more information, please read The Slimmening proposal.
I wasn't able to get the ReactNative <WebView/> to work at all in my Expo app. So switching to the react-native-community/react-native-webview <WebView/> component worked for me. I hope that helps!
Try out this:
import { WebView } from 'react-native-webview';
export default AppWebview = () => (
<View style={styles.container}>
<WebView
source={{uri: 'https://www.youtube.com/embed/MhkGQAoc7bc'}}
style={styles.video}
/>
<WebView
source={{uri: 'https://www.youtube.com/embed/PGUMRVowdv8'}}
style={styles.video}
/>
</View>
);
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'space-between',
},
video: {
marginTop: 20,
maxHeight: 200,
width: 320,
flex: 1
}
});

Flexbox View does not wrap Image in React Native

When I have an Image inside a View with 'flex: 1' the View does not wrap the Image.
When I paste my code into react-native-web-player it works as expected..
The right image is what I expected, while the left is the actual result:
import * as React from 'react';
import { AppRegistry, View, Image, Text, StyleSheet } from 'react-native';
import SplitView from './components/SplitView';
function PurchaseLine() {
// tslint:disable-next-line:max-line-length
const imgUrl =
'https://cdn.shopify.com/s/files/1/0938/8938/products/10231100205_1_1315x1800_300_CMYK_1024x1024.jpeg?v=1445623369';
return (
<View style={styles.container}>
<Image source={{ uri: imgUrl }} style={styles.img} />
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: 'red'
},
img: {
width: 45,
height: 62
}
});
export default class Datakasse extends React.Component<object, object> {
render() {
return (
<View>
<PurchaseLine />
</View>
);
}
}
AppRegistry.registerComponent('Datakasse', () => Datakasse);
UPDATE:
"height: 100%" or "flex: 1" on the outermost container, and not setting "flex: 1" on PurchaseLine's container seems to work.. Confused why I can't set the latter tho..
import * as React from 'react';
import { AppRegistry, View, Image, Text, StyleSheet } from 'react-native';
import SplitView from './components/SplitView';
function PurchaseLine() {
// tslint:disable-next-line:max-line-length
const imgUrl =
'https://cdn.shopify.com/s/files/1/0938/8938/products/10231100205_1_1315x1800_300_CMYK_1024x1024.jpeg?v=1445623369';
return (
<View style={styles.container}>
<Image source={{ uri: imgUrl }} style={styles.img} />
<Text>1 x Jacket</Text>
<Text>$99.99</Text>
</View>
);
}
const styles = StyleSheet.create({
container: {
backgroundColor: 'red',
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
padding: 10
},
img: {
width: 45,
height: 62
}
});
export default class Datakasse extends React.Component<object, object> {
render() {
return (
<View style={{ height: '100%', backgroundColor: 'blue' }}>
<PurchaseLine />
</View>
);
}
}
AppRegistry.registerComponent('Datakasse', () => Datakasse);
You can make use of a react-native "hack" and define the width as null like { width: null }. This will make it stretch at 100%. See also the example here based on your code
UPDATE:
the alignSelf what you are looking for. Sample here
UPDATE:
Try this example by setting flex on the parent element and remove from child. Your parent element wasnt defined as flex component so the child had issues. Check here
i removed the flex from container and added here
<View style={{flex: 1}}>