control components placement with flexbox - css

I have the following APP. I'm having trouble with the spacing of components within the return of the App class.
I would like to move the 'Reset' up a little bit and the 'Start' down a little. It would be nice if there was an easy way to control the vertical placement
import React from 'react';
import { Button,StyleSheet, Text, View } from 'react-native';
export class Timers extends React.Component{
constructor(props){
super(props)
this.state={work:{min:this.props.min,
sec:this.props.sec,
buttton:this.props.button,
period:this.props.period,},
play:{min:this.props.min,
sec:this.props.sec,
buttton:this.props.button,
start:this.props.start,
period:this.props.period,}
}
}
render(){
return(
<View style={styles.timer}>
<Text>{this.props.name}</Text>
<Text>{'min: ' + this.props.min + ' sec: ' + this.props.sec }</Text>
<Text>{this.props.period}</Text>
</View>
)
}
}
export default class App extends React.Component {
constructor(){
super()
this.state={start:'Start'}
}
parentState(){
if(this.state.start === 'Start') startStop = 'Stop'
else startStop = 'Start'
this.setState({start:startStop})
}
buttonPress(x){
if(x === 'Start' || x === 'Stop')this.parentState()
console.log(x)
}
render() {
return (
<View style={styles.container}>
<Button style={styles.top} title='Reset'onPress=
{()=>this.buttonPress(this.state.start)}/>
<View style={styles.row}>
<Timers
name={'WORK'}
min={'25'}
sec={'00'}
button={'Reset'}
period={'tbd'} >
</Timers>
<Timers
name={'PLAY'}
min={'25'}
sec={'00'}
period={'tbd'} >
</Timers>
</View>
<Button title={this.state.start} onPress=
{()=>this.buttonPress(this.state.start)}/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection:'column',
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
timer:{
flex:1,
flexDirection:'column',
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
row:{
flex:0,
flexDirection:'row',
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});

apply marginTop and MarginBottom to styles.row does the trick

Related

React WebkitAppRegion Warnings

Ok, so I'm extremely new to react, so sorry if this question is really dumb.
I've been working on a react application using electron and expo, and don't fully understand how to solve this warning which is showing in my developer console.
Warning: Failed prop type: Invalid props.style key `WebkitAppRegion` supplied to `View`.
Bad object: {
"display": "flex",
"flexDirection": "row",
"height": 20,
"backgroundColor": "#0e0e11",
"margin": 0,
"borderBottomWidth": 0.5,
"borderColor": "#060607",
"WebkitAppRegion": "drag"
}
When I originally built the design for this UI, I did so with standard html and SCSS, and now I'm attempting to change it to react as my first big project. So having done some googling, I found the information that to include my -webkit-app-region: drag all I needed to do was CammelCase and remove the "-"'s. Except it's now throwing this error, it does the function as intended but how does one solve the "invalid props style" issue?
Some shitty code for ya to critique xD
//app.tsx
import React from 'react';
import { Platform, StyleSheet, Text, View } from 'react-native';
import { SplashScreen } from 'expo';
import * as Font from 'expo-font';
import * as styles from './assets/styles/main'
SplashScreen.preventAutoHide();
setTimeout(SplashScreen.hide, 10000);
export default class App extends React.Component {
state = {
fontLoaded: false,
};
async componentDidMount() {
await Font.loadAsync(styles.fontList);
this.setState({ fontLoaded: true });
}
render() {
return (
this.state.fontLoaded ? (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'stretch', backgroundColor: styles.colors.dark1 }}>
<this.DisplayHandles />
</View>
) : null
);
}
DisplayHandles() {
if (Platform.OS === 'web' && process.versions.electron) {
return ([
<View style={[styles.electron.header, {WebkitAppRegion: 'drag'}]}>
<View style={styles.electron.titleContainer}>
<Text key='title' style={[styles.electron.title, {WebkitAppRegion: 'no-drag', 'userSelect': 'none'}]}> Smartcloud</Text>
</View>
<View style={styles.electron.controlContainer}>
<Text key='minimize' style={[styles.electron.button, {WebkitAppRegion: 'no-drag', 'userSelect': 'none'}]} onClick={handleClick}>-</Text>
<Text key='maximize' style={[styles.electron.button, {WebkitAppRegion: 'no-drag', 'userSelect': 'none'}]} onClick={handleClick}>+</Text>
<Text key='close' style={[styles.electron.button, {WebkitAppRegion: 'no-drag', 'userSelect': 'none'}]} onClick={handleClick}>x</Text>
</View>
</View>,
<View style={{ flex: 1}}>
<Content.CreateHandles />
</View>
]
)
}
return <Content.Container/>
}
}
function handleClick(e) {
e.preventDefault();
console.log('I was clicked')
}
class Content {
static CreateHandles() {
return (
<View>
<Content.Container />
</View>
)
}
static Container () {
return (
<View style={{alignItems: 'center',}}>
<Content.TestingText />
</View>
)
}
static TestingText() {
if (Platform.OS === 'web') {
if (process.versions.electron) {
return (<Text style={{fontSize: 60, color: styles.colors.light5, fontFamily: styles.rubik.medium} }> This is a Electron {process.versions.electron} + {Platform.OS} version </Text>)
}
return (<Text style={{fontSize: 60, color: styles.colors.light5, fontFamily: styles.rubik.medium}}> This is a {Platform.OS} version </Text>)
}
return <Text style={{fontSize: 20, color: styles.colors.light5, fontFamily: styles.rubik.medium}}> This is a {Platform.OS} version</Text>
}
}
// ./assets/styles/main.tsx
export const electron = StyleSheet.create({
header: {
display: 'flex',
flexDirection: 'row',
height: 20,
backgroundColor: colors.dark4,
margin: 0,
borderBottomWidth: 0.5,
borderColor: colors.dark5,
},
titleContainer: {
display: 'flex',
alignItems: 'flex-start',
flexGrow: 1,
},
controlContainer: {
display: 'flex',
justifyContent: 'flex-end',
flexDirection: 'row',
alignItems: 'center',
},
title: {
color: colors.purple,
margin: 0,
marginLeft: 10,
fontSize: 14,
fontFamily: rubik.black,
},
button: {
width: 25,
margin: 0,
marginLeft: 10,
color: colors.purple,
textAlign: 'center',
fontSize: 14,
fontFamily: rubik.black,
}
})

Flexbox in react native : How to align 2 items at the center of the screen?

I discovered flexbox recently and I'm struggling to make it work, I'm surely missed some concept that make me hard time to understands it's mechanics so here is what I have:
It's a preview camera screen
with a back button on the top right
A text in the middle
and a record button to shoot some images
Here is what I have at the moment:
this is done with this React native component (style included)
import React from "react";
import { RNCamera } from "react-native-camera";
import { StyleSheet, TouchableOpacity, View, Platform} from "react-native";
import {Icon, Text} from "native-base";
import RequestPermissions from "../components/Permissions/RequestPermissions";
import I18n from "../i18n/i18n";
/**
* This is the component which allows the user to film his own film
*/
export default class CameraScreen extends React.Component
{
constructor(props) {
super(props);
this.camera = null;
}
state = {
isRecording: false,
iconVid: "record",
iconMode: null,
overlay: true
};
/**
* With RNCamera, it seems that permission is always asked to the user... Maybe this code is then irrelevant
*/
componentWillMount() {
if (Platform.OS === "android") {
RequestPermissions().then(() => {
console.log("granted");
}).then((err) => {
console.log(err)
});
}
}
componentWillUnmount() {
this.stopRecording();
};
stopRecording = () => {
if (this.camera) {
this.camera.stopRecording();
this.setState({
isRecording: false,
iconVid: "record"
});
}
};
renderCamera = () => {
return (
<View style={styles.container}>
<RNCamera
ref={cam => {
this.camera = cam;
}}
style={styles.preview}
>
<View style={styles.controlsContainer}>
<View style={styles.topRightButton}>
<TouchableOpacity onPress={() => this.props.navigation.goBack()}>
<Icon name={"arrow-left"} type={"Feather"} style={styles.iconFurtive}/>
</TouchableOpacity>
</View>
<View style={styles.middleContainer}>
<Text style={styles.actionText}>{I18n.t("action_text").toUpperCase()}</Text>
</View>
<View style={styles.leftContainer}>
<TouchableOpacity onPress={() => this.recordVideo()}>
<Icon name={this.state.iconVid} type={"MaterialCommunityIcons"} style={styles.iconCamera}/>
</TouchableOpacity>
</View>
</View>
</RNCamera>
</View>
);
};
/**
* For more options
* https://github.com/react-native-community/react-native-camera/blob/master/docs/RNCamera.md#recordasyncoptions-promise
*/
recordVideo = () => {
if (this.camera) {
this.setState({ isRecording: true, iconVid: "stop" });
// Show the overlay
console.log("Device is Recording");
this.camera.recordAsync({maxDuration: 15}).then(data => {
this.stopRecording();
console.log("Stop Recording");
console.log(data);
}).catch((err) => {
console.log(err);
this.stopRecording();
});
}
};
render() {
return this.renderCamera()
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
marginTop:30,
},
controlsContainer: {
flex: 1,
flexDirection: "column"
},
topRightButton: {
flex: 1,
justifyContent: 'flex-start',
alignItems: 'flex-start',
},
middleContainer: {
flex: 0.5,
justifyContent: 'center',
alignItems: 'center',
},
leftContainer: {
flex: 0.5,
justifyContent: 'center',
alignItems: 'flex-end',
},
actionText: {
color: "#fff",
fontSize: 72
},
preview: {
flex: 1,
},
iconCamera: {
color: "#ff4459",
marginBottom: 50,
padding: 25,
backgroundColor: "#fff",
borderRadius: 50,
},
iconFurtive: {
color: "#fff",
marginTop: 50,
marginLeft: 50,
}
});
Here is what I want:
How to do that with flexbox? What am I missing?
Code changed at View with {styles.topRightButton}
return (
<View style={styles.container}>
<RNCamera
ref={cam => {
this.camera = cam;
}}
style={styles.preview}
>
<View style={styles.controlsContainer}>
<View style={{justifyContent: 'flex-start', alignItems: 'flex-start',}}>
<TouchableOpacity onPress={() => this.props.navigation.goBack()}>
<Icon name={"arrow-left"} type={"Feather"} style={styles.iconFurtive}/>
</TouchableOpacity>
</View>
<View style={{flex: 1, flexDirection: 'row', alignItems: 'center', justifyContent: 'space-around'}}>
<View style ={{height: 50, width: 50, backgroundColor: 'transparent'}} />
<Text style={styles.actionText}>{I18n.t("action_text").toUpperCase()}</Text>
<TouchableOpacity onPress={() => this.recordVideo()}>
<Icon name={this.state.iconVid} type={"MaterialCommunityIcons"}/>
</TouchableOpacity>
</View>
</View>
</RNCamera>
</View>
);
For middle and left the content should be in the same div with that div having a flexDrirection: 'row'. This puts them in the same row.
The controls container can have justifyContent: 'center', and alignItems: 'center'.
The topRightButton should override the parents style.

React Native Modal Transparent Not Working

So I want to use a Modal to disable all interactions on a screen but I still want everything on the screen to be visible. It's odd because it was working just fine for me earlier, then I tried to make the Modal its own component, but as soon as I did that, it stopped working properly. I then went back to what I originally did but still having the same issue. I should've committed it when it worked.
Any idea where I went wrong?
Here's my code:
import React, { Component } from 'react';
import { View, Image, Modal, Text, Button, TouchableHighlight } from 'react-native';
constructor(props) {
super(props);
this.state = {
modalVisible: true,
};
}
openModal() {
this.setState({modalVisible: true});
}
closeModal() {
this.setState({modalVisible: false});
}
render() {
return (
<View style={styles.container}>
<Modal
visible={this.state.modalVisible}
onRequestClose={() => this.closeModal()}
>
<TouchableHighlight
style={styles.modalContainer}
onPress={() => this.closeModal()}
>
<Text>"Words n stuff"</Text>
</TouchableHighlight>
</Modal>
<View
style={styles.upperContainer}
/>
<View
style={styles.lowerContainer}
/>
</View>
);
}
}
}
Styles:
modalContainer: {
flexGrow: 1,
justifyContent: 'center',
flexDirection: 'row',
backgroundColor: 'transparent',
},
container: {
flexGrow: 1,
justifyContent: 'space-around',
flexDirection: 'column',
alignItems: 'center',
},
upperContainer: {
flexGrow: 2,
alignItems: 'center',
justifyContent: 'flex-end',
paddingBottom: 18,
width: screenWidth,
marginTop: -140,
},
lowerContainer: {
flexGrow: 2,
alignItems: 'center',
justifyContent: 'space-around',
width: screenWidth,
},
Try to add transparentproperty to your Modal.
Example:
<Modal
transparent
...>
...
</Modal>
Doc: https://facebook.github.io/react-native/docs/modal.html#transparent
Try transparent={true} on <Modal />

How to use Flex in a Row for its two Child Views in React Native?

My code is like this---
import React from 'react';
import {View,Text,Alert,StyleSheet} from 'react-native';
const data = ['All','Electronics','Baby and Child','Property'];
const styles=StyleSheet.create({
itemStyles: {
color: "#F456A3",
fontSize:30,
fontWeight:"bold",
},
CategoryStyle: {
flex:1,
justifyContent:'center',
flexDirection:'row'
}
});
export default class FilterScreen extends React.Component {
constructor(){
super();
this.test;
}
renderCategories = () =>{
//Alert.alert(data[0]);
this.test=data.map(item => {
return(
<View key={item} style={styles.CategoryStyle}>
<Text style={styles.itemStyles}>{item}</Text>
</View>
)
})
return this.test;
}
render(){
return(
<View>
<Text>hello world</Text>
{this.renderCategories()}
</View>
)
}
}
I have to apply styling to the Text present in render categories such that it should come with 2 text in a row. So, here there will be 2 rows with 2 texts.
How can that be done?
For styles.itemStyles set it to width: '50%' and add flexWrap to parent. Try this:
const styles=StyleSheet.create({
itemStyles: {
color: "#F456A3",
fontSize:30,
fontWeight:"bold",
width: '50%' ///////////////// i added this
},
CategoryStyle: {
flex:1,
justifyContent:'center',
flexDirection:'row',
flexWrap: 'wrap' ///////// added this
}
});
Here is a snack expo that works - https://snack.expo.io/BJY_WnrrG
import React, { Component } from 'react';
import { Text, View, StyleSheet } from 'react-native';
export default class App extends Component {
render() {
return (
<View style={styles.container}>
<Text style={[styles.text, styles.textPink]}>a</Text>
<Text style={[styles.text, styles.textBlue]}>b</Text>
<Text style={[styles.text, styles.textPink]}>c</Text>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
height: '100%',
flexDirection: 'row',
justifyContent: 'flex-end',
flexWrap: 'wrap',
alignContent: 'space-around',
alignItems: 'flex-start',
backgroundColor: 'steelblue'
},
text: {
width: '50%'
},
textBlue: {
backgroundColor: 'skyblue'
},
textPink: {
backgroundColor: 'pink'
}
});
When items wrap, you get the new style property of alignContent check it out - http://facebook.github.io/react-native/docs/layout-props.html#aligncontent
Also when items wrap, justifyContent only affects rows where there is space left over, as seen in the third text item above.

React Native NavigatorIOS Does not Render component

I am having a problem rendering my component inside of a navigatorIOS, I am sure it is a style issue but I can't pinpoint where.
I have given flex : 1
removed backgroundColor
and I have given a margin
as suggested in other stack overflow questions.
If I throw MessageBoardTopics outside of the navigator it renders fine.
import MessageBoardTopics from './messageBoardTopics.js';
class MessageBoards extends React.Component{
constructor(props){
super(props);
}
componentDidMount(){
}
render() {
return (
<View style={styles.container}>
<NavigatorIOS
style={{flex: 1}}
initialRoute={{
component: MessageBoardTopics,
title: 'Forum',
}}/>
</View>
);
}
};
module.exports = MessageBoards;
var styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
});
var screenWidth = Dimensions.get('window').width;
class MessageBoardTopics extends React.Component{
constructor(props){
super(props);
var ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
var data = PostStore.getState().posts;
this.state={sortText: 'Sort by: Old',
dataSource: ds.cloneWithRows(data)};
}
componentDidMount() {
PostStore.listen(this.onChange);
}
componentWillUnmount() {
PostStore.unlisten(this.onChange);
}
onChange(state) {
this.setState(state);
}
replyToMessage(){
}
removeMessage(){
}
sortMessages(){
}
editMessage(){
}
pressRow(rowData){
this.props.navigator.push({
title: rowData.title,
component: Topic
});
}
render() {
return (
<View style={styles.container}>
<Text>fasfasdfafasdf</Text>
<View style={{flex: .2}}></View>
<View style={styles.buttonBar}>
<TouchableHighlight style={styles.centerButton} underlayColor={"lightred"} onPress={this.sortMessages}>
<Text>{this.state.sortText}</Text>
</TouchableHighlight>
<View style={styles.centerButton} underlayColor={"lightred"} onPress={this.newMessage}>
<ComposeModal reply={this.replyToMessage} index={null}/>
</View>
</View>
<ListView
dataSource={this.state.dataSource}
style={{borderTopWidth: 2}}
renderRow={(rowData) =>
<TouchableHighlight underlayColor="lightgrey" onPress={()=>this.pressRow(rowData)}>
<View style={styles.message}>
<Text style={styles.messageTitle}>{rowData.title}</Text>
<Text style={styles.messageAuthor}>By: <Text style={{color: 'blue', fontStyle: 'italic'}}>{rowData.author}</Text></Text>
</View>
</TouchableHighlight>}/>
</View>
);
}
};
module.exports = MessageBoardTopics;
var styles = StyleSheet.create({
container: {
flex: 1,
marginTop: 80,
},
message: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'white',
borderWidth: 1,
borderColor: "lightblue",
padding: 15,
},
messageTitle: {
color: 'grey',
textDecorationLine: 'underline',
fontWeight: 'bold',
},
messageAuthor: {
fontSize: 10,
},
buttonBar: {
flex: .1,
alignSelf: 'stretch',
alignItems: 'center',
flexDirection: 'row',
},
centerButton: {
flex: 1,
width: (screenWidth/2),
alignItems: 'center',
},
button: {
flex: 1,
textAlign: 'center',
},
});
I needed to set a width to a wrapper component for the navigatorIOS
Edit: When I upgraded from react-native 0.16 to 0.17 flex:1 was not working on the navigatorIOS. I had to create a wrapper component and give that a flex as well.
This did not work. This was in my index.ios.js file, which rendered the navigatorIOS on 0.16.
render() {
return (
<View style={styles.container}>
<NavigatorIOS
style={{flex: 1, alignSelf: 'stretch'}}
initialRoute={{
component: MessageBoardTopics,
title: 'Forum',
}}/>
</View>
);
}
};
on react-native 0.17 I had to create a wrapper component and give that a flex attribute. I had to change my index.ios.js to render this instead.
var forumComponent = React.createClass({
render: function() {
return (
<View style={styles.container}>
<MessageBoards style={{flex: 1}}/>
</View>
);
}
});

Resources