Related
I am new to CSS skills.
I didn't learn much about it.
I have a question about how to make an element have full width.
I added my code down below, but the simplest way I tried didn't work which is width: '100%'.
I have a code in react native, so components are nested in order I put. The higher code is a parent of code right down to it.
I would like elements in RideCard.js, each ride card, to have expand fully next to DateDay.js. I could have seen that once I removed flexDirection: row in oneDayContainer in MonthBody.js, the elements expanded fully.
But I would like to keep the design.
Thanks in advance.
MonthBody > DateDay + RideList >
MonthBody.js
import { StyleSheet } from "react-native";
import { View } from "react-native";
import { useFirestoreContext } from "../../contexts/FirestoreContext";
import { DateDay } from "./DateDay";
import { RideList } from "./RideList";
export const MonthBody = ({ monthYear }) => {
const { rides } =
useFirestoreContext();
return (
<View style={styles.monthBodyContainer}>
{Object.keys(rides[monthYear]).map((dateDay, j) => {
return (
<View style={styles.oneDayContainer}>
<DateDay dateDay={dateDay} />
<RideList monthYear={monthYear} dateDay={dateDay} />
</View>
);d
})}
</View>
);
}
const styles = StyleSheet.create({
monthBodyContainer: {
display: "flex",
flexDirection: "column",
},
oneDayContainer: {
display: "flex",
flexDirection: "row",
alignItems: "flex-start",
},
});
DateDay.js
import { StyleSheet, Text, View } from "react-native";
export const DateDay = ({dateDay}) => {
return (
<View style={styles.dateDayContainer}>
<Text style={styles.dayText}>{dateDay.split("-")[1]}</Text>
<Text style={styles.dateText}>{dateDay.split("-")[0]}</Text>
</View>
);
};
const styles = StyleSheet.create({
dateDayContainer: {
display: "flex",
flexDirection: "column",
alignItems: "center",
justifyContent: "center",
width: 50,
marginRight: 20,
marginTop: 10,
},
dateText: {
fontSize: 16,
textAlign: "center",
},
dayText: {
fontSize: 12,
textAlign: "center",
},
});
RideList.js
import { StyleSheet, Text, View } from "react-native";
import { COLOR } from "../../assets/variables";
import { useFirestoreContext } from "../../contexts/FirestoreContext";
import { RideCard } from "./RideCard";
export const RideList = ({ monthYear, dateDay }) => {
const { rides } = useFirestoreContext();
return (
<View style={styles.rideList}>
{rides[monthYear][dateDay].map((ride, k) => {
// return <RideCard key={k} ride={ride} />;
return <RideCard key={k} ride={ride} />;
})}
</View>
);
};
const styles = StyleSheet.create({
rideList: {
marginBottom: 5,
},
});
RideCard.js
import { StyleSheet, Text, View } from "react-native";
import { COLOR } from "../../assets/variables";
export const RideCard = ({ ride }) => {
console.log("RideCard", ride);
return (
<View
style={[
styles.container,
ride.boardType === "NEED"
? { backgroundColor: COLOR.lightGreen, borderWidth: .3, borderColor: COLOR.green }
: { backgroundColor: COLOR.lightBlue, borderWidth: .3, borderColor: COLOR.blue },
]}
>
<View style={styles.places}>
<Text style={styles.placeText}>{ride.cityFrom}</Text>
<Text> - </Text>
<Text style={styles.placeText}>{ride.cityTo}</Text>
</View>
<View>
<Text style={styles.dateText}>
{ride.leavingHour}:{ride.leavingMinutes}
</Text>
</View>
</View>
);
};
const styles = StyleSheet.create({
container: {
padding: 10,
marginBottom: 5,
borderRadius: 10,
},
places: {
display: "flex",
flexDirection: "row",
alignItems: "center",
marginBottom: 5,
},
});
On the CardList styles you can add flex: 1 to the rideList.
const styles = StyleSheet.create({
rideList: {
marginBottom: 5,
flex: 1,
},
});
I'm trying to use a useRef hook so a scrollview and my pan gesture handler can share a common ref. but once I initialize the useRef() hook and pass it to both components, it breaks with this error
TypeError: Attempted to assign to readonly property.
I've tried typecasting and adding types to the useRef call but it returns the same error. Can someone help please?
My component:
import { StyleSheet, Text, View, Image, Dimensions } from "react-native";
import React from "react";
import {
PanGestureHandler,
PanGestureHandlerGestureEvent,
PanGestureHandlerProps,
} from "react-native-gesture-handler";
import Animated, {
runOnJS,
useAnimatedGestureHandler,
useAnimatedStyle,
useSharedValue,
withTiming,
} from "react-native-reanimated";
import { FontAwesome } from "#expo/vector-icons";
export interface InfluencerItemProps
extends Pick<PanGestureHandlerProps, "simultaneousHandlers"> {
id?: string;
name: string;
userName: string;
profileImg: string;
rating?: Number;
onDismiss?: (Item: InfluencerItemProps) => void;
}
const ITEM_HEIGHT = 65;
const { width: SCREEN_WIDTH } = Dimensions.get("window");
const TRANSLATE_X_THRESHOLD = -SCREEN_WIDTH * 0.3;
const InfluencerItem = (props: InfluencerItemProps) => {
const { name, userName, profileImg, onDismiss, simultaneousHandlers } = props;
const translateX = useSharedValue(0);
const marginVertical = useSharedValue("2%");
const R_Height = useSharedValue(ITEM_HEIGHT);
const opacity = useSharedValue(1);
const panGesture = useAnimatedGestureHandler<PanGestureHandlerGestureEvent>({
onActive: (event) => {
translateX.value = event.translationX;
},
onEnd: () => {
const shouldbeDismissed = translateX.value < TRANSLATE_X_THRESHOLD;
if (shouldbeDismissed) {
translateX.value = withTiming(-SCREEN_WIDTH);
R_Height.value = withTiming(0);
marginVertical.value = withTiming("0%");
opacity.value = withTiming(0, undefined, (isFinished) => {
if (isFinished && onDismiss) {
runOnJS(onDismiss)(props);
}
});
} else {
translateX.value = withTiming(0);
}
},
});
const rStyle = useAnimatedStyle(() => ({
transform: [
{
translateX: translateX.value,
},
],
}));
const rIconContainerStyle = useAnimatedStyle(() => {
const opacity = withTiming(
translateX.value < TRANSLATE_X_THRESHOLD ? 1 : 0
);
return { opacity };
});
const RContainerStyle = useAnimatedStyle(() => {
return {
height: R_Height.value,
opacity: opacity.value,
marginVertical: marginVertical.value,
};
});
return (
<Animated.View style={[styles.wrapper, RContainerStyle]}>
<Animated.View style={[styles.iconContainer, rIconContainerStyle]}>
<FontAwesome name="trash" size={ITEM_HEIGHT * 0.5} color="white" />
</Animated.View>
<PanGestureHandler
simultaneousHandlers={simultaneousHandlers}
onGestureEvent={panGesture}
>
<Animated.View style={[styles.container, rStyle]}>
<Image
source={{
uri: profileImg,
}}
style={styles.image}
/>
<View style={styles.text}>
<Text style={styles.name}>{name}</Text>
<Text style={styles.userName}>{userName}</Text>
</View>
</Animated.View>
</PanGestureHandler>
</Animated.View>
);
};
export default InfluencerItem;
const styles = StyleSheet.create({
wrapper: {
width: "100%",
alignItems: "center",
},
container: {
flexDirection: "row",
borderWidth: 1,
borderRadius: 12,
height: ITEM_HEIGHT,
width: "100%",
backgroundColor: "#FFFFFF",
},
image: {
marginVertical: 10,
marginHorizontal: "4%",
height: 48,
width: 48,
borderRadius: 50,
},
text: {
justifyContent: "center",
alignItems: "flex-start",
marginHorizontal: 6,
},
name: {
fontSize: 14,
fontWeight: "500",
color: "#121212",
},
userName: {
fontSize: 12,
fontWeight: "400",
color: "#121212",
},
iconContainer: {
height: ITEM_HEIGHT,
width: ITEM_HEIGHT,
backgroundColor: "red",
position: "absolute",
right: "2.5%",
justifyContent: "center",
alignItems: "center",
},
});
InfluencerItem.defaultProps = {
name: "UserName",
userName: "userName",
profileImg:
"https://d2qp0siotla746.cloudfront.net/img/use-cases/profile-picture/template_0.jpg",
rating: "4",
};
This is my Screen:
import {
StyleSheet,
Text,
View,
SafeAreaView,
TextInput,
ScrollView,
} from "react-native";
import { StatusBar } from "expo-status-bar";
import React, { useCallback, useRef, useState } from "react";
import InfluencerItem from "../../components/InfluencerItem";
import { InfluencerItemProps } from "../../components/InfluencerItem";
// import { ScrollView } from "react-native-gesture-handler";
type Props = {};
const Saved = (props: Props) => {
const [search, setSearch] = useState<string>("");
const [influencerData, setInfluencerData] = useState(influencerz);
const handleSearch = () => {
console.log(search);
};
const onDismiss = useCallback((Item: InfluencerItemProps) => {
setInfluencerData((influencers) =>
influencers.filter((item) => item.id !== Item.id)
);
}, []);
const ref = useRef(null); //useRef initialization
return (
<SafeAreaView style={{ flex: 1 }}>
<View style={styles.container}>
<View style={styles.saved}>
{/* Saved Kikos component goes in here */}
<ScrollView ref={ref}> //passed ref here
{influencerData.map((influencer) => (
<InfluencerItem
key={influencer.id}
name={influencer.name}
userName={influencer.handle}
profileImg={influencer.image}
onDismiss={onDismiss}
simultaneousHandlers={ref} //also passed ref here
/>
))}
</ScrollView>
</View>
<Text style={styles.bottomText}>No Saved Kikos again</Text>
</View>
</SafeAreaView>
);
};
export default Saved;
const styles = StyleSheet.create({
container: {
paddingHorizontal: "4%",
},
headerText: {
color: "#121212",
fontWeight: "700",
lineHeight: 30,
fontSize: 20,
marginTop: 40,
},
search: {
borderRadius: 12,
backgroundColor: "#D9D9D9",
fontSize: 14,
lineHeight: 21,
color: "#7A7B7C",
paddingLeft: 10,
paddingRight: 5,
height: 45,
marginTop: 15,
position: "relative",
},
innerSearch: {
position: "absolute",
top: 30,
right: 10,
},
saved: {
backgroundColor: "rgba(217, 217, 217, 0.15)",
marginTop: 22,
paddingVertical: "7%",
marginBottom: 34,
},
bottomText: {
fontSize: 14,
fontWeight: "500",
textAlign: "center",
},
});
Use createRef() instead of useRef() as mentioned in the documentation.
const imagePinch = React.createRef();
return (
<RotationGestureHandler
simultaneousHandlers={imagePinch}
....
There is a complete example here in TypeScript.
Also make sure to use Animated version of components wherever applicable (<Animated.View> instead of <View>, <Animated.Image> instead of <Image> etc)
When I submit a form in React Native I get the below error undefined is not an object (evaluating 'title.length'). This problem occurs when I submit a form when the Card.js should be rendering the data from the form. I have checked and its getting the data back fine, seems to be a problem with rendering the data that its reading as undefined. After this error the form actually submits successfully and the Card.js displays the data.
Card.js
import React from "react";
import {
StyleSheet,
View,
Text,
ImageBackground,
TouchableOpacity,
} from "react-native";
const Card = (props) => {
const {
navigation,
title,
address,
homeType,
description,
image,
yearBuilt,
price,
id,
} = props;
return (
<TouchableOpacity
onPress={() => props.navigation.navigate("HomeDetail", { houseId: id })}
>
<View style={styles.card}>
<View style={styles.titleContainer}>
<Text style={styles.title}>
{title.length > 30 ? title.slice(0, 30) + "..." : title}
</Text>
</View>
<View style={styles.imageContainer}>
<ImageBackground source={{ uri: image }} style={styles.image}>
<Text style={styles.price}>${price}</Text>
<View style={styles.year}>
<Text style={styles.yearText}>{yearBuilt}</Text>
</View>
</ImageBackground>
</View>
<View style={styles.description}>
<Text style={styles.descriptionText}>
{description.length > 100
? description.slice(0, 100) + "..."
: description}
</Text>
</View>
</View>
</TouchableOpacity>
);
};
const styles = StyleSheet.create({
card: {
shadowColor: "black",
shadowOpacity: 0.25,
shadowOffset: { width: 0, height: 2 },
shadowRadius: 8,
borderRadius: 10,
backgroundColor: "#ffffff",
elevation: 5,
height: 300,
margin: 10,
},
titleContainer: {
height: "15%",
padding: 10,
},
title: {
fontSize: 18,
fontWeight: "bold",
color: "gray",
},
imageContainer: {
width: "100%",
height: "65%",
overflow: "hidden",
},
image: {
width: "100%",
height: "100%",
flexDirection: "row",
justifyContent: "space-between",
alignItems: "flex-end",
},
price: {
fontSize: 30,
color: "#fff",
margin: 10,
},
year: {
margin: 10,
backgroundColor: "#2652B0",
height: 25,
width: 80,
borderRadius: 5,
},
yearText: {
fontSize: 20,
color: "#fff",
textAlign: "center",
},
description: {
margin: 10,
},
descriptionText: {
fontSize: 16,
color: "gray",
},
});
export default Card;
HomeListScreen.js
import React, { useEffect, useState } from "react";
import {
StyleSheet,
View,
Text,
FlatList,
ActivityIndicator,
} from "react-native";
import { FloatingAction } from "react-native-floating-action";
import { useDispatch, useSelector } from "react-redux";
import Card from "../components/Card";
import * as houseAction from "../redux/actions/houseAction";
const HomeListScreen = (props) => {
const dispatch = useDispatch();
const [isLoading, setIsLoading] = useState(false);
const { houses } = useSelector((state) => state.house);
useEffect(() => {
setIsLoading(true);
dispatch(houseAction.fetchHouses())
.then(() => setIsLoading(false))
.catch(() => setIsLoading(false));
}, [dispatch]);
if (isLoading) {
return (
<View style={styles.centered}>
<ActivityIndicator size="large" />
</View>
);
}
if (houses.length === 0 && !isLoading) {
return (
<View style={styles.centered}>
<Text>No home found. You could add one!</Text>
</View>
);
}
return (
<View style={styles.container}>
<FlatList
data={houses}
keyExtractor={(item) => item._id}
renderItem={({ item }) => (
<Card
navigation={props.navigation}
title={item.title}
address={item.address}
homeType={item.homeType}
description={item.description}
price={item.price}
image={item.image}
yearBuilt={item.yearBuilt}
id={item._id}
/>
)}
/>
<FloatingAction
position="right"
animated={false}
showBackground={false}
onPressMain={() => props.navigation.navigate("AddHome")}
/>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
},
centered: {
flex: 1,
justifyContent: "center",
alignItems: "center",
},
});
export default HomeListScreen;
<Text style={styles.title}>
{ title ? (title.length > 30 ? title.slice(0, 30) + "..." : title):true}
</Text>
Make sure that title is not undefined.
I'm learning React Native and need help from the React Native experts out there! Does anyone know how to redirect a link to new page(component).
I have a list of items (Purchases, Settings, Polices, Customer Support) that I want to redirect them to a new page when I click on it. Do I need to use the onPress event or is there another way?
import React, { component} from 'react';
import {Component} from 'react';
import { StyleSheet, Text, View, TextInput, TouchableOpacity } from 'react-native';
import Login from './LogIn';
class Profile extends Component{
state = {
names: [
{
id: 0,
name: 'Purchases',
},
{
id: 1,
name: 'Settings',
},
{
id: 2,
name: 'Policies',
},
{
id: 3,
name: 'Feedback',
},
{
id: 3,
name: 'Customer support',
},
{
id: 3,
name: 'About the app',
}
]
}
render(){
return(
<View style={styles.container}>
<Text style={styles.header}>Welcome to GOLDENSHOE</Text>
<Text style={{fontSize: 16}}>Sign up or log in to access special discounts, your favorites and your account </Text>
<Login />
<View>
{
this.state.names.map((item, index) => (
<TouchableOpacity
key = {item.id}
style = {styles.listCont}
onPress = {() => console.log('hello')}>
<Text style = {styles.text}>
{item.name}
</Text>
</TouchableOpacity>
))
}
</View>
<View style={{marginRight: 50}}>
<Text style={{marginTop: 40, textAlign:"right",fontWeight: "bold"}}>STAY IN TOUCH</Text>
<TextInput style={{textAlign:"right", marginTop: 10, borderColor: 'black'}}placeholder="Sign up for GOLDENSHOE news" type="text" />
</View>
</View>
)
}
}
const styles = StyleSheet.create({
container: {
marginLeft: 10
},
header: {
fontWeight: 'bold',
marginTop: 40,
marginBottom: 30,
color: "lightgreen",
fontSize: 30,
},
button: {
alignItems: 'flex-start',
marginTop: 30,
flexDirection: 'column',
borderBottomColor: "black",
borderBottomWidth: 1,
borderTopColor: "black",
borderTopWidth: 1,
},
listCont: {
padding: 10,
marginTop: 3,
borderBottomWidth: 1
},
login: {
borderRadius: 10
}
})
export default Profile;
I'm reading Learning React Native by Bonnie Eisenman and am having trouble with the WeatherProject tutorial in chapter 3. When the app loads in the iOS simulator, it appears to be rendering the contents of Forecast.js but taking up the whole display without anything from WeatherProject.js
Here is my code:
index.ios.js
import {
AppRegistry,
} from 'react-native';
import WeatherProject from './WeatherProject';
AppRegistry.registerComponent('WeatherProject', () => WeatherProject);
WeatherProject.js
import React, {
Component,
} from 'react';
import {
StyleSheet,
Text,
View,
TextInput,
} from 'react-native';
var Forecast = require('./Forecast');
var styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#4D4D4D'
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10
},
input: {
fontSize: 20,
borderWidth: 2,
height: 40
}
});
var WeatherProject = React.createClass({
getInitialState() {
return {
zip: '',
forecast: {
main: 'Clouds',
description: 'few clouds',
temp: 45.7
}
}
},
_handleTextChange(event) {
console.log(event.nativeEvent.text);
this.setState({
zip: event.nativeEvent.text
});
},
render() {
return (
<View style={styles.container}>
<Text style={styles.welcome}>
You input {this.state.zip}.
</Text>
<Forecast
main={this.state.forecast.main}
description={this.state.forecast.description}
temp={this.state.forecast.temp}/>
<TextInput
style={styles.input}
returnKeyType="go"
onSubmitEditing={this._handleTextChange}/>
</View>
);
}
});
module.exports = WeatherProject;
Forecast.js
import React, {
Component,
} from 'react';
import {
StyleSheet,
Text,
View,
} from 'react-native';
var styles = StyleSheet.create({
bigText: {
flex: 2,
fontSize: 20,
textAlign: 'center',
margin: 10,
color: '#FFFFFF'
},
mainText: {
flex: 1,
fontSize: 16,
textAlign: 'center',
color: '#FFFFFF'
}
});
var Forecast = React.createClass({
render() {
return (
<View>
<Text style={styles.bigText}>
{this.props.main}
</Text>
<Text style={styles.mainText}>
Current conditions: {this.props.description}
</Text>
<Text style={styles.bigText}>
{this.props.temp}°F
</Text>
</View>
);
}
});
module.exports = Forecast;
The expected outcome looks like this (from the book):
But my actual outcome is this:
And here is the view debug hierarchy:
Any help at all would be greatly appreciated.
Add this style in Forecast:
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center'
}
then add the style into the View:
<View styles={style.container}>