React-native flex height - react-native

I have 3 components and I am trying to set their heights (header, body, footer) but when it renders, each component has just the height of one line of text it contains.
import React from 'react';
import { View, Text } from 'react-native';
import Header from './Header';
import Body from './Body';
import Footer from './Footer';
import * as globalStyles from '../styles/global';
const HomeScreen = () => (
<View style={{ flex: 1 }}>
<Header style={{ flex: 1 }} title={'MyTitle'}>
<Text>Component</Text>
</Header>
<Body style={{ flex: 3 }}>
<Text>my body</Text>
</Body>
<Footer style={{ flex: 1 }}>
<Text>my footer</Text>
</Footer>
</View>
);
export default HomeScreen;
App
import React from 'react';
import { Provider } from 'react-redux';
import HomeScreen from './components/HomeScreen';
import createStore from './createStore';
const store = createStore();
export default () => (
<Provider store={store}>
<HomeScreen />
</Provider>
);
Header
import React, { PropTypes } from 'react';
import { View, Text, StyleSheet } from 'react-native';
import * as globalStyles from '../styles/global';
const Header = ({ children, title }) => (
<View>
<Text style={globalStyles.COMMON_STYLES.text}>
{children}
{title}
{title}
</Text>
</View>
);
Header.propTypes = {
children: PropTypes.node
};
const styles = StyleSheet.create({
header: {
paddingTop: 20
}
});
export default Header;
Footer
import React, { PropTypes } from 'react';
import { View, Text, StyleSheet } from 'react-native';
import * as globalStyles from '../styles/global';
const Footer = ({ children }) => (
<View>
<Text style={globalStyles.COMMON_STYLES.text}>
{children}
</Text>
</View>
);
Footer.propTypes = {
children: PropTypes.node.isRequired
};
const styles = StyleSheet.create({
header: {
marginTop: 20,
flex: 1,
}
});
export default Footer;
Body
import React, { PropTypes } from 'react';
import { View, Text, StyleSheet } from 'react-native';
import * as globalStyles from '../styles/global';
const Body = ({ children, title }) => (
<View>
<Text style={globalStyles.COMMON_STYLES.text}>
{children}
{title}
{title}
</Text>
</View>
);
Body.propTypes = {
children: PropTypes.node
};
const styles = StyleSheet.create({
header: {
marginTop: 20,
flex: 1,
}
});
export default Body;
global styles
import { StyleSheet } from 'react-native';
export const BG_COLOR = '#343336';
export const BAR_COLOR = '#4e4d52';
export const TEXT_COLOR = '#e5dbda';
export const HEADER_TEXT_COLOR = '#fff';
export const MUTED_COLOR = '#8e8786';
export const LINK_COLOR = '#48e9d9';
export const ACCENT_COLORS = ['#d31d65', '#751c53', '#c248c0', '#7d6e8b', '#bbc6f7'];
export const COMMON_STYLES = StyleSheet.create({
pageContainer: {
backgroundColor: BG_COLOR,
marginTop: 0,
paddingTop: 5,
paddingHorizontal: 10
},
text: {
color: TEXT_COLOR,
fontFamily: 'Helvetica Neue'
}
});
My understanding is that the Body should be 3 x the height of header or footer.
React-native:
react-native-cli: 2.0.1
react-native: 0.41.2

EDIT
Flex should be given to your root containers of the header, body and footer components. Header, Footer and Body are custom components, the style props won't be applicable to them, the style you applied just get passed as a prop
const Footer = ({ children }) => (
<View style={{ flex: 1 }}> // root container of footer
<Text style={globalStyles.COMMON_STYLES.text}>
{children}
</Text>
</View>
);
const Body = ({ children, title }) => (
<View style={{ flex: 3 }}>
<Text style={globalStyles.COMMON_STYLES.text}>
{children}
{title}
{title}
</Text>
</View>
);
const Header = ({ children, title }) => (
<View style={{ flex: 1 }}> // root container of header
<Text style={globalStyles.COMMON_STYLES.text}>
{children}
{title}
{title}
</Text>
</View>
);
Hope its working for you

Related

Why is MyContext.Provider not showing value in render?

I am a newbie trying to work with react native context. A very simple program, but unable to show the value.
Here is the code:
import React, {Component} from 'react';
import {Text, View } from 'react-native';
export const MyContext = React.createContext();
export default class App extends Component {
static contextType = MyContext;
render() {
this.state = 1
return (
<View>
<Text> Hello There </Text>
<MyContext.Provider value={this.state}>
{this.props.children}
</MyContext.Provider>
</View>
);
};
};
'Hello There' gets displayed. Even if I hard-code the value for MyContext.Provider , it doesn't display anything, and there are no errors either. What am I doing wrong?
Here is an sample with a class component.
You have to create a context React.createContext
You have to apply your context with MyContext.Provider
You have to consume your context with MyContext.Consumer
import { Text, View } from 'react-native';
export const MyContext = React.createContext();
export default class App extends Component {
state = { value: 12};
render() {
return (
<MyContext.Provider value={this.state}>
<View
style={{ justifyContent: 'center', alignItems: 'center', flex: 1 }}>
<Text>Hello There </Text>
<MyContext.Consumer>
{({ value }) => <Text>{value}</Text>}
</MyContext.Consumer>
</View>
</MyContext.Provider>
);
}
}
Kindly check context example. hope it helps
Please check the working example here https://snack.expo.dev/#gaurav1995/excited-donut
import React,{useContext,useState,createContext} from 'react';
import { Text, View, StyleSheet } from 'react-native';
import Constants from 'expo-constants';
const BasicContext = createContext({})
const BasicComp = () => {
const dummyText = useContext(BasicContext);
return(
<View style={styles.container} >
<Text>{dummyText?.hey}</Text>
</View>
)
}
export default function App() {
const [reach,setReach] = useState({ hey:"whatsup devs! loving context"})
return (
<BasicContext.Provider value={reach} >
<BasicComp />
</BasicContext.Provider>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
padding: 8,
},
});

Error : You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports

I got this error when trying to import and use another component that I have created in another file. And I got an error like this :
Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.
Check the render method of `Sidebar`.
This is my code to export component as default component in customDrawer.js which file is same directory:
const Sidebar = ({ isDarkTheme, setIsDarkTheme, ...props }) => {
const handlePress = () => {
props.navigation.dispatch(DrawerActions.closeDrawer());
props.navigation.navigate("Settings");
};
const { colors } = useTheme();
const toggleTheme = () => {
setIsDarkTheme();
};
// console.log('navi--?',props.navigation);
return (
<Container style={{ backgroundColor: colors.background }}>
<Header
style={{
backgroundColor: colors.background,
borderBottomWidth: 0,
marginTop: 70,
borderWidth: 0,
}}
>
<StatusBar barStyle="dark-content" backgroundColor="#ffffff" />
<Right>
<Button transparent>
<TouchableOpacity onPress={() => handlePress()}>
{/* <Ionicons name="ios-options" size={28} color={colors.icon} /> */}
</TouchableOpacity>
</Button>
</Right>
</Header>
<Content>
<DrawerContentScrollView {...props}>
<DrawerItemList {...props} />
</DrawerContentScrollView>
<TouchableOpacity>
<View
style={{
display: "flex",
flexDirection: "row",
alignItems: "center",
paddingRight: 20,
paddingLeft: 20,
paddingTop: 10,
}}
>
<Text style={{ flex: 1, color: colors.text }}>Dark Theme</Text>
<View>
<Switch onValueChange={toggleTheme} value={isDarkTheme} />
</View>
</View>
</TouchableOpacity>
</Content>
</Container>
);
};
const styles = StyleSheet.create({});
export default Sidebar;
And then, in my App.js I have import components like this :
import Sidebar from "./customDrawer";
All imports I use in customDrawer.js :
import {
DrawerContentScrollView,
DrawerItemList,
} from "#react-navigation/drawer";
import { Button, Container, Content, Header, Right } from "native-base";
import React, { useState } from "react";
//import { Ionicons } from "#expo/vector-icons";
import { StyleSheet, Text, View, Switch } from "react-native";
import { StatusBar } from "react-native";
import { TouchableOpacity } from "react-native";
import { DrawerActions } from "#react-navigation/native";
import { useTheme } from "#react-navigation/native";

ReferenceError: Can't find variable: SearchBar in React Native

I got an error called "ReferenceError: Can't find variable: SearchBar". I tried to check for syntax error and run the app again. But the same error appeared. How can I rectify it? Thanks.
This is my SearchScreen.js file.
import React, { useState } from 'react';
import { StyleSheet, View, TextInput } from 'react-native';
const SearchScreen = () => {
const [term, setTerm] = useState('')
return (
<View>
<SearchBar
term={term}
onTermChange={(newTerm) => setTerm(newTerm)} />
</View>
);
}
const styles = StyleSheet.create({});
export default SearchScreen;
This is my SearchBar.js file.
import React from 'react';
import { StyleSheet, View, TextInput } from 'react-native';
import { EvilIcons } from '#expo/vector-icons'
const SearchBar = ({ term, onTermChange }) => {
return (
<View style = {styles.background}>
<EvilIcons style={styles.icon} name="search" />
<TextInput
value={term}
style={styles.input}
placeholder="Search"
onChangeText={newTerm => onTermChange(newTerm)} />
</View>
);
}
const styles = StyleSheet.create({
background: {
height: 50,
borderRadius: 6,
marginHorizontal: 15,
flexDirection: 'row',
alignItems: 'center'
},
input: {
flex: 1
},
icon: {
fontSize: 35,
alignSelf: 'center',
marginHorizontal: 15
}
});

Cannot read property 'navigation' of undefined Evaluating App.js Loading App.js

Looking to have button enter go into another screen:
need help with navigation screen.
I keep getting error:
Cannot read property 'navigation' of undefined
Evaluating App.js
Loading App.js
TypeError: Cannot read property 'navigation' of undefined
https://snack.expo.io/#ganiyat1/colorful-thrills
import * as React from 'react';
import { Text, View, StyleSheet, ImageBackground, Image, Button } from 'react-native';
import Constants from 'expo-constants';
import { StackNavigator} from 'react-navigation';
import Books from './components/Books';
// You can import from local files
// or any pure javascript modules available in npm
import { Card } from 'react-native-paper';
const Book = StackNavigator({
Books: { screen: Books },
});
const { navigate } = this.props.navigation;
export default function App() {
return (
<View style={styles.container}>
<View style={styles.topContainer}>
<Text style={styles.title}> Colorful Thrills
</Text >
</View>
<View style={styles.bottomContainer}></View>
<View style={styles.imageContainer}>
<Image
style={styles.image}
source={require('./assets/bookcover.png')}
/>
<Text style={styles.paragraph}>
{"\n"} BOOKWORMS, UNITE! {"\n"} {"\n"}
Suspense, Mystery and Thrillers by Authors of Color
</Text>
<Button
color='#ff914d'
title= 'ENTER'
onPress={() =>
navigate('Books')}
/>
</View>
</View>
);
}
In the above code snippet, I don't see a default Navigator being returned form the entry file, which is App.js by default in React Native.
I assume that you just started to learn React Native, so I will spare you all the minor details and walk you through the solution.
I refactored the App.js file to a into a new component file in /components/Home.js.
Added a default stack Navigator in App.js which has two screens, Home and Books.
Now you can access all the Navigation props in your Home and Books component, as it is being declared in the Navigator variable in App.js
Here is a live demo of your code on Expo.
//App.js
import * as React from 'react';
import { Text, View, StyleSheet, ImageBackground, Image, Button } from 'react-native';
import Constants from 'expo-constants';
import { StackNavigator} from 'react-navigation';
import Books from './components/Books';
import Home from './components/Home'
import { Card } from 'react-native-paper';
const Navigator = StackNavigator({
Books: { screen: Books },
Home:{screen:Home}
});
export default function App(props) {
return (
<Navigator />
);
}
//component/Books.js
import React, { useState } from 'react';
import { StyleSheet, SafeAreaView,Button } from 'react-native';
import MaterialTabs from 'react-native-material-tabs';
const Books = (props) => {
const {navigation} = props
const [selectedTab, setSelectedTab] = useState(0);
return (
<SafeAreaView style={styles.container}>
<MaterialTabs
items={['New Releases', 'All', 'BOM']}
selectedIndex={selectedTab}
onChange={setSelectedTab}
barColor="#1fbcd2"
indicatorColor="#ff914d"
activeTextColor="white"
/>
<Button
color='#ff914d'
title= 'Home'
onPress={() =>
navigation.navigate('Home')}
/>
</SafeAreaView>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
},
});
export default Books
//component/Home.js
import React from 'react'
import {View,Text,StyleSheet,Button,Image} from 'react-native'
const Home = (props) => {
const {navigation} = props
return (
<View style={styles.container}>
<View style={styles.topContainer}>
<Text style={styles.title}> Colorful Thrills
</Text >
</View>
<View style={styles.bottomContainer}></View>
<View style={styles.imageContainer}>
<Image
style={styles.image}
source={require('../assets/bookcover.png')}
/>
<Text style={styles.paragraph}>
{"\n"} BOOKWORMS, UNITE! {"\n"} {"\n"}
Suspense, Mystery and Thrillers by Authors of Color
</Text>
<Button
color='#ff914d'
title= 'ENTER'
onPress={() =>
navigation.navigate('Books')}
/>
</View>
</View>
)
}
export default Home
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'column',
},
topContainer: {
flex: 1,
backgroundColor: '#ff914d',
},
bottomContainer: {
flex: 1,
backgroundColor: '#96d0e3',
},
imageContainer: {
position: 'absolute',
width: '100%',
height: '100%',
justifyContent: 'center',
alignItems: 'center',
},
image: {
width: 300,
},
title:{
margin: 24,
marginTop: 50,
fontSize: 40,
fontWeight: 'bold',
textAlign: 'center',
fontFamily: 'GillSans-Italic',
},
paragraph: {
margin: 24,
marginTop: 0,
fontSize: 20,
fontWeight: 'bold',
textAlign: 'center',
}
});

react native rendering useless gap(area) issue with flex

I am a newcomer for React Native with expo, so still struggling with the flex even though reading many documents. As an attached image, there is a gap, red rectangle area in the image, between header and router style in the Home component. I tried to remove that area but have no idea so far. Could you give me any advice?
Component: Home
import React, { useEffect, useState } from 'react';
import { StyleSheet, Text, View, Button, FlatList, Dimensions } from 'react-native';
import LocationBar from "./locationBar";
import { Router, Scene } from 'react-native-router-flux';
import Item from "../Item/item";
import Main from "./main";
export default function Home() {
return (
<>
<View style={styles.header}>
<LocationBar />
</View>
<Router style={styles.router}>
<Scene key="root">
<Scene key="main" component={Main} initial={true} />
<Scene key="item" component={Item} />
</Scene>
</Router>
</>
);
}
const width_proportion = '100%';
const height_proportion = '15%';
const styles = StyleSheet.create({
header: {
flex:0.15,
backgroundColor: 'yellow',
width: width_proportion,
},
router: {
flex: 1,
backgroundColor: 'blue',
width: width_proportion,
justifyContent: 'center',
alignItems: 'center'
},
});
Component: Item
import * as React from 'react';
import { View, StyleSheet, Dimensions, Text, Button, FlatList, } from 'react-native';
import { TabView, SceneMap } from 'react-native-tab-view';
const FirstRoute = () => (
<View style={[styles.scene, { backgroundColor: '#ff4081' }]} />
);
const SecondRoute = () => (
<View style={[styles.scene, { backgroundColor: '#673ab7' }]} />
);
const initialLayout = { width: Dimensions.get('window').width };
export default function Item({ menu, itemId }) {
const [index, setIndex] = React.useState(0);
const [routes] = React.useState([
{ key: 'first', title: 'First' },
{ key: 'second', title: 'Second' },
]);
const renderScene = SceneMap({
first: FirstRoute,
second: SecondRoute,
});
return (
<>
<TabView
navigationState={{ index, routes }}
renderScene={renderScene}
onIndexChange={setIndex}
initialLayout={initialLayout}
>
);
}
const styles = StyleSheet.create({
scene: {
flex: 1,
},
});
Component: Location
import React, { useEffect, useState } from 'react';
import { StyleSheet, Text, View, Button } from 'react-native';
import MaterialIcons from 'react-native-vector-icons/MaterialIcons';
import * as Location from "expo-location";
export default function LocationBar() {
const [lat, setLat] = useState();
const [lon, setLon] = useState();
useEffect(() => {
...
});
return (<View style={styles.container}>
<MaterialIcons name="location-on" size={30} />
<Text>
({lat}-{lon})
</Text>
</View>);
}
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
flexDirection: 'row',
marginTop: 10
},
});
I got the answer from this post! hideNavBar={true} is the key to hide that area