FlatList doesn't show title tags at all - javascript

I'm quite new at react-redux, and currently am trying to build some stack application that will simply be some type of menu that will have it's sections with titles and when pressing the title it will show some simple text about it. So I'm using Flatlist for rendering all these sections, and the rendering works perfectly fine. It renders exactly 9 sections which is the number of my current objects, meaning that it has access to the data, plus when I try to change the font size of the title that these sections have to display, the size of the sections change as well, meaning that it definitely has access to the title strings as well, but for some reason the text is not showing up at all.
Here's how it looks:
I tried to change the text color, change size, change background color, add some padding, but section still doesn't show the text.
So here's where I implement the FlatList:
import React, { Component } from 'react';
import { FlatList } from 'react-native';
import { connect } from 'react-redux';
import ListItem from './ListItem';
class LibraryList extends Component {
renderItem(library) {
return <ListItem library={library} />;
}
render() {
console.log(this.props.libraries);
return (
<FlatList
data={this.props.libraries}
renderItem={this.renderItem}
keyExtractor={(library) => library.id.toString()}
/>
);
}
}
const mapStateToProps = state => {
return { libraries: state.libraries };
};
export default connect(mapStateToProps)(LibraryList);
Here I implement the section itself:
import React, { Component } from 'react';
import { Text } from 'react-native';
import { CardSection } from './common';
class ListItem extends Component {
render() {
const { titleStyle } = styles;
return (
<CardSection>
<Text style={titleStyle}>
{this.props.library.title}
</Text>
</CardSection>
);
}
}
const styles = {
titleStyle: {
color: 'black',
fontSize: 20,
fontWeight: '600',
}
};
export default ListItem;
And here's the code for the section itself:
import React from 'react';
import { View } from 'react-native';
const CardSection = (props) => {
return (
<View style={styles.containerStyle}>
{props.children}
</View>
);
};
const styles = {
containerStyle: {
borderBottomWidth: 1,
padding: 5,
backgroundColor: '#fff',
justifyContent: 'flex-start',
flexDirection: 'row',
borderColor: '#ddd',
}
};
export { CardSection };
Expected result would be for titles to show up in those 9 sections.

In ListItem replace {this.props.library.title} with {this.props.library.item.title} within the Text component.

Related

The pre-configured props set from within the React child is overriding the custom props passed from the parent

The fontSize: 20 and color: 'red' props are displaying instead of the fontSize: 12 and color: 'blue' that is set from the Parent component, but the fontWeight: 'bold' is correctly displayed.
I have a reusable React UI child component that receives some props from its parent like so
import React from "react";
import { Text, StyleSheet } from "react-native";
const BodyText = ( props ) => {
return (
<Text style={styles.bodyText} {...props} >{props.children}</Text>
);
};
const styles = StyleSheet.create({
bodyText: {
fontSize: 20,
color: 'red'
},
});
export default BodyText;
The parent component looks like this
import React from "react";
import { StyleSheet } from "react-native";
import BodyText from './components/UI/BodyText'
const Parent = () => {
return (
<BodyText style={styles.text} >Hi There</BodyText>
);
};
const styles = StyleSheet.create({
text: {
fontSize: 12,
color: 'blue',
fontWeight: 'bold'
},
});
export default Parent;
Interestingly when I play around in CodePen, it is displaying correctly but not on my local setup.
Implement your BodyText.js like this
import React from 'react';
import { Text, StyleSheet } from 'react-native';
const BodyText = (props) => {
const { style, children, ...rest } = props; // Destructure props here...
return (
<Text style={[styles.bodyText, style]} {...rest}>
{children}
</Text>
);
};
const styles = StyleSheet.create({
bodyText: {
fontSize: 20,
color: 'red',
},
});
export default BodyText;
Working Example Snack
You can use default props as well:
import React from "react";
import { Text, StyleSheet } from "react-native";
const BodyText = ( props ) => {
return (
<Text style={{
fontSize: props.fontSize,
color: props.color
}}>
{props.children}</Text>
);
};
BodyText.defaultProps = {
fontSize:20,
color:'red'
}
export default BodyText;
After you can use you component with new props or not:
<BodyText fontSize={12} color='blue'>Hi There</BodyText>

Horizontal margin too big on newly created Expo app

I just created a React Native app with Expo using expo init. Everything went fine. Then I went on and created a Home screen like so:
import React from 'react';
import { View, TextInput } from 'react-native';
export default class HomeScreen extends React.Component {
state = {
searchText: ""
}
render() {
return (
<View
style={{
flex: 1,
backgroundColor: 'white'
}}
>
<TextInput
placeholder="Search..."
value={this.state.searchText}
onChangeText={ (searchText) => this.setState({ searchText }) }
/>
</View>
);
}
}
I added it to my AppNavigator...
import { createAppContainer } from 'react-navigation';
import { createStackNavigator } from 'react-navigation-stack';
import HomeScreen from '../screens/HomeScreen';
const AppNavigator = createStackNavigator({
Home: HomeScreen
});
export default createAppContainer(AppNavigator);
...which I in turn added to App.js:
import React from 'react';
import { StyleSheet, View, StatusBar, Platform } from 'react-native';
import { AppLoading } from 'expo';
import AppNavigator from './navigation/AppNavigator';
export default class App extends React.Component {
state = {
isLoadingComplete: false
}
render() {
if (!this.state.isLoadingComplete && !this.props.skipLoadingScreen) {
return (
<AppLoading
startAsync={this._loadResourcesAsync}
onError={this._handleLoadingError}
onFinish={this._handleFinishLoading}
/>
);
}
return (
<View style={styles.container}>
{Platform.OS === 'ios' && <StatusBar barStyle="default" />}
<AppNavigator />
</View>
);
}
_loadResourcesAsync = async () => { };
_handleLoadingError = error => {
console.warn(error);
};
_handleFinishLoading = () => {
this.setState({ isLoadingComplete: true });
};
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
Now, my problem is that my app looks like this:
As you can see, the horizontal margins are way too big, but I never set them to be like that. What am I doing wrong? I want the TextInput to stretch across the full screen.
Your HomeScreen Component will be as wide as its contents. You did not specify the width of the main View, therefore, it adjusted itself to be as wide the components inside. What you can do to resolve this issue is that you must provide width property in your Top level View's style.
And in order to get the Width of the screen, you can import Dimensions from react-native and use that like below:
const windowWidth = Dimensions.get('window').width;
and finally, you can assign the windowWidth to your view like so:
style={{flex:1, width: windowWidth, backgroundColor: 'white'}}

How can I update the styling of a component based on some variable?

I'm working on an app in React Native. I want to make it so the styling of the panel labels on the bottom of the screen updates based on the panel the user is on.
As of now, I can get the index of the current panel that's showing, but I don't know how to make that update the styling of the labels.
The first panel
and the second panel
Basically when you use the same component and want to style it in different ways, your component's style property depends on either props or state. There are many ways to put different styles depending on your state/props, I'll provide just a few of them:
Ternary operation based on current state.
import React from 'react';
import { View, Text, StyleSheet } from 'react-native';
const styles = StyleSheet.create({ // Your styles go here
labelFirstTab: {
textColor: 'red',
},
labelSecondTab: {
textColor: 'blue',
},
});
class MyApp extends React.Component {
state = {
currentTab: 0,
};
getLabelStyles = () => {
const { currentTab } = this.state;
return currentTab === 0 ? styles.labelFirstTab : styles.labelSecondTab;
};
render() {
return (
<View style={{ flex: 1 }}>
{/* Let's say this is your label */}
<Text style={this.getLabelStyles()}>Hi! I'm a nice label.</Text>
</View>
);
}
}
Additional styling based on props (also could depend on state, it doesn't matter).
import React from 'react';
import { View, Text, StyleSheet } from 'react-native';
const styles = StyleSheet.create({
label: {
fontSize: 16,
textColor: 'black',
},
labelDarkMode: {
textColor: 'lightgrey',
},
}); // Your styles go here
class MyApp extends React.Component {
getLabelStyles = () => {
const { isDarkMode } = this.props;
const { label, labelDarkMode } = styles;
return [styles.label, isDarkMode && styles.labelDarkMode];
};
render() {
return (
<View style={{ flex: 1 }}>
{/* Let's say this is your label */}
<Text style={this.getLabelStyles()}>Hi! I'm a nice label.</Text>
</View>
);
}
}
You even can pass your styles directly from your props, leaving the whole logic to your parent component. Just make sure that you've passed styles from your parent component to the current one.
import React from 'react';
import { View, Text, StyleSheet } from 'react-native';
class MyApp extends React.Component {
render() {
const { labelStyles } = this.props;
return (
<View style={{ flex: 1 }}>
{/* Let's say this is your label */}
<Text style={labelStyles}>Hi! I'm a nice label.</Text>
</View>
);
}
}
Thank you E. Dn! This worked! Here's what I did.
const [activePanel, setActivePanel] = useState('nowPanel');
Swiping between panels calls a function:
const swipeNavigation = (index) => {
if (index === 0) {
setActivePanel('nowPanel');
} else {
setActivePanel('todayPanel');
}
};
Then within the actual View I want to style:
style={activePanel === 'nowPanel' ? styles.activePanel : null,}>

Set styling from parent component (props) and from component itself react native

is it possible to set some styling properties from the parent as props and some styling properties from the component itself?
Here is my component:
import React,{ Component } from 'react';
import { View, Text } from 'react-native';
class BackgroundMar extends Component {
render(){
return (
<View style={[styles.viewStyle]}>
<Text>{this.props.test}</Text>
</View>
)
}
};
var styles = {
viewStyle: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: props.color
}
};
export default BackgroundMar;
And here is my parent:
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import BackgroundMar from "./components/BackgroundMar";
export default class App extends React.Component {
render() {
return (
<BackgroundMar
test={'aaa'}
color={'#ff2044'}
/>
);
}
};
});
I would like to set only the backgroundColor from the parent.
Okay I found the solution.
On the parent:
export default class App extends React.Component {
render() {
return (
<BackgroundMar
test={'#52a03f'}
/>
);
}
};
On the component itself:
class BackgroundMar extends Component {
render(){
return (
<View style={[styles.viewStyle, { backgroundColor: this.props.test}]}>
<Text>{this.props.test}</Text>
</View>
)
}
};
var styles = {
viewStyle: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
}
};
Try something like
First send styles from parent as object... ex ..
style={{color:"#abcd"}}
then inside the child component. add that to style array
<View style={this.props.style ? [styles.viewStyle, this.props.style] :
[styles.viewStyle]}>

Getting 'undefined is not an object' when calling navigation prop methods in react native navigation

I'm having trouble calling react navigation methods from custom components outside of my original screens, specifically the one I'm working on right now is trying to call goBack() in a back arrow of a custom header component I made (code below). The error message I'm getting when I click the back arrow is:
undefined is not an object (evaluating '_this2.props.navigation.goBack')
Here is the code:
// HeaderText.js
import React from 'react';
import { View, Text, StyleSheet, TouchableOpacity, Platform } from 'react-native';
import { Icon } from 'expo';
export class HeaderText extends React.Component {
render() {
const needsBackButton = this.props.backIcon;
if (needsBackButton) {
return(
<View style={[styles.headerStyle,styles.buttonHeaderStyle]}>
<TouchableOpacity onPress={() => this.props.navigation.goBack()} style={styles.backButtonStyles}><Icon.Ionicons size={25} style={{ color: '#fff', fontWeight: 'bold' }} name={Platform.OS === 'ios' ? `ios-arrow-back` : 'md-arrow-back'} /></TouchableOpacity>
<Text style={styles.textStyle}>{this.props.headerText}</Text>
<View style={styles.emptyViewStyles} />
</View>
);
} else {
return(
<View style={styles.headerStyle}>
<Text style={styles.textStyle}>{this.props.headerText}</Text>
</View>
);
}
}
}
Here is the screen I'm putting that HeaderText component in:
// SubmitReferralScreen.js
import React from 'react';
import {
Image,
Platform,
ScrollView,
StyleSheet,
Text,
TouchableOpacity,
View,
ImageBackground
} from 'react-native';
import { MonoText } from '../../components/general/StyledText';
import { HeaderText } from '../../components/general/HeaderText';
import { HomeScreenContainer } from '../../components/homeScreen/HomeScreenContainer';
import { IconButton } from '../../components/general/IconButton';
import { StatusInfo } from '../../constants/StatusInfo';
import SvgUri from 'react-native-svg-uri';
export default class SubmitReferralScreen extends React.Component {
static navigationOptions = {
header: null,
};
render() {
return (
<View style={{flex: 1, width: '100%',justifyContent: 'center', alignItems: 'center'}}>
<ImageBackground source={require('../../assets/images/background.png')} style={{width: '100%', height: '100%', flex: 1, justifyContent: 'flex-start', alignItems: 'center', backgroundColor: 'background-color: rgba(0, 0, 0, 0.5)',}}>
<HeaderText backIcon='true' headerText='New Referral' />
<Text>Submit referral here!</Text>
</ImageBackground>
</View>
);
}
}
And here is my Stack Navigator for the referral Screens:
// MainTabNavigator.js
const ReferralStack = createStackNavigator({
Referrals: ReferralScreen,
MakeReferral: SubmitReferralScreen,
});
I've looked at this StackOverflow answer: Getting undefined is not an object evaluating _this.props.navigation
And the answer there was to put only navigation.navigate(YourScreen). I tried that, and the error I got said "cannot find variable navigation".
How can I call navigation props from custom react native components?
By default only screen components are provided with the navigation prop. You can either use library provided ways of hooking up arbitrary components to the navigation state, or you can pass navigation as a prop manually.
Option #1. Using withNavigation:
React navigation exports a higher-order component through which you can inject the navigation props into any component you want. To do this, you can do something like:
Don't immediately export the HeaderText component class (remove export from that line)
At the bottom of that file add export default withNavigation( HeaderText );
or if you don't want to use a default export and keep it as a named export, instead do:
const NavigationConnected = withNavigation( HeaderText );
export { NavigationConnected as HeaderText };
Option #2. Passing navigation as prop: In your SubmitReferralScreen component you can simply pass this.props.navigation as a prop to the HeaderText component like: <HeaderText navigation={ this.props.navigation } />
It's because your navigation prop didn't found where is the navigation's value prop from the parent. Better you make HeaderText component using regular arrow function, like this;
const HeaderText = ({ needsBackButton }) => {
if(needsBackButton) {
return (
<View style={[styles.headerStyle,styles.buttonHeaderStyle]}>
<TouchableOpacity onPress={() => this.props.navigation.goBack()} style={styles.backButtonStyles}><Icon.Ionicons size={25} style={{ color: '#fff', fontWeight: 'bold' }} name={Platform.OS === 'ios' ? `ios-arrow-back` : 'md-arrow-back'} /></TouchableOpacity>
<Text style={styles.textStyle}>{this.props.headerText}</Text>
<View style={styles.emptyViewStyles} />
</View>
)
}
return (
// another component
)
}
And then, You can simply use useNavigation() to access navigation prop from any screen/component.
First, import useNavigation on component that handled function of the moving screen.
import { useNavigation } from '#react-navigation/native';
Create some constant to reference this module:
const navigation = useNavigation()
And then, simply use this on your TouchableOpacity's onPress prop like this;
<TouchableOpacity
onPress={() => navigation.goBack()}
style={styles.backButtonStyles}
>
//...
</ TouchableOpacity>
Get the complete documentation on this:
https://reactnavigation.org/docs/connecting-navigation-prop/

Categories