I want to make a 2 by 2 table from the two given arrays. The table should look like this:
I have to use 'map' function from ES6. My code looks below.
import React, {Component} from 'react';
import {Text, View} from 'react-native';
const array1 = ['1','2'];
const array2 = ['X','Y']
class Table extends Component{
render() {
return (
<View style={{borderStyle : 'solid',justifyContent : 'center' }}>
{array1.map((arr1) => (
<View>
{array2.map((arr2) => (
<View>
<Text>
{arr2} {arr1}
</Text>
</View>
))}
</View>
))
}
</View>
);
}
}
export default Table;
At this moment I am getting a output like - X1 X2 Y1 Y2
I need to use flex. What do I do?
You are almost there. You just need to make sure that the last level of views are flex and have a direction of 'row'.
return (
<View style={{ borderStyle: 'solid', justifyContent: 'center' }}>
{array1.map((arr1) => (
<View style={{flexDirection: 'row'}}> {/* This is the main line you need to change */}
{array2.map((arr2) => (
<View style={{padding: 5, borderColor: 'black', borderWidth: 1}}>
<Text style={{color: 'red'}}>
{arr2}{arr1}
</Text>
</View>
))}
</View>
))}
</View>
);
You can look at a working snack example here.
Related
I have encountered a weird issue in the newest react native where the value in the text input in a component remains when a tab is switched.
I can't figure what is going on and I thought it should re-render when tab is changed but it doesn't.
Here's my code
app.js
export default function App() {
const [tab, setTab] = useState("TAB1")
return (
<View style={styles.container}>
<View style={{ flexDirection: 'row' }}>
<TouchableOpacity
style={{ borderRadius: 5, borderWidth: 1, marginRight: 5, padding: 20 }}
onPress={() => setTab("TAB1")}
>
<Text>Tab 1</Text>
</TouchableOpacity>
<TouchableOpacity
style={{ borderRadius: 5, borderWidth: 1, padding: 20}}
onPress={() => setTab("TAB2")}
>
<Text>Tab 2</Text>
</TouchableOpacity>
</View>
<View style={{ marginTop: 20}}>
{
tab === "TAB1" ? (
<View>
<InputComponent tab={tab} />
</View>
) : (
<View>
<InputComponent tab={tab} />
</View>
)
}
</View>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
marginTop: 100,
padding: 10
},
});
inputcomponent.js
export function InputComponent({ tab }) {
const [value, setValue] = useState("");
return (
<View>
<Text>{tab}</Text>
<TextInput placeholder="INPUT HERE" value={value} onChangeText={setValue}/>
</View>
)
}
It seems like the input component re-renders but the text input within it doesn't change.
Demo Issue
This is such a good question. This is because we are importing it once and passing it to two different components. It changes the tab but uses the same textinput state because they are using the same key.
To fix this pass in the key prop so React knows that tab changed:
{
tab === "TAB1" ? (
<View>
<InputComponent key={1} tab={tab} />
</View>
) : (
<View>
<InputComponent key={2} tab={tab} />
</View>
)
}
Snack: https://snack.expo.io/mVVLb9uId
Read about keys: https://reactjs.org/docs/lists-and-keys.html#keys
import React from 'react'
import { View, Text, StyleSheet, TouchableWithoutFeedback } from "react-native";
const Header = props => {
const {
navigationState,
navigation,
activeTintColor,
inactiveTintColor
} = props;
const activeTabIndex = navigation.state.index;
return (
<View style={styles.containerHeader}>
<View style={styles.textContainer}>
<Text style={styles.textWhite}>Win Bets</Text>
<Text style={styles.textWhiteSmall}>win cash daily</Text>
</View>
<View style={styles.tabContainer}>
{navigationState.routes.map((route, index) =>{
const isRouteActive = index === activeTabIndex;
const tintColor = isRouteActive ? activeTintColor : inactiveTintColor;
return (
<TouchableWithoutFeedback
onPress={() => navigation.navigate(route.routeName)}
key={route.routeName}
>
<View>
<Text
style={{
fontSize: 17,
textTransform: "capitalize",
color: `${tintColor}`,
fontWeight: `${isRouteActive ? "700" : "normal"}`
}}
>
{route.routeName}
</Text>
</View>
</TouchableWithoutFeedback>
);
})}
</View>
</View>
);
};
the tabs show as they are supposed to be, but they are not clickable and cant navigate to a different page... also the home page doesnt show.
what could be the problems, or how do i configure the routes and routeName?
on my react-native app I would like to have premium content for people who paid a subscription.
My issue is how I make the content to display as unavailable(if you are not premium ) and the same as the other content if you are premium. Basically I would like the premium content to be displayed with a "lock overlay" on it for non-premium users.
However, I do not know how I set this conditional. It is a matter of state? If yes where should be positioned this state considering that is unidirectional?
Just to be clear I will have premium and non premium content
class Browser extends Component {
scrollX = new Animated.Value(0);
renderRecommended = () => {
return (
<View style={[styles.flex, styles.column, styles.recommended]}>
<View style={[styles.row, styles.recommendedHeader]}>
<Text
style={{
fontSize: theme.sizes.font * 1.4,
alignSelf: 'center',
color: 'white',
fontFamily: 'Nunito-Bold',
}}>
Recommended
</Text>
</View>
<View style={[styles.column, styles.recommendedList]}>
<FlatList
horizontal
scrollEnabled
showsHorizontalScrollIndicator={false}
scrollEventThrottle={16}
snapToAlignment="center"
style={[styles.shadow, {overflow: 'visible'}]}
data={this.props.destinations}
keyExtractor={(item, index) => `${item.id}`}
renderItem={({item, index}) =>
this.renderRecommendation(item, index)
}
/>
</View>
</View>
);
};
renderRecommendation = (item, index) => {
const {destinations} = this.props;
const isLastItem = index === destinations.length - 1;
const {navigation} = this.props;
return (
<TouchableOpacity
onPress={() =>
this.props.navigation.navigate('PreScreen', {
item,
})
}>
<View
style={[
styles.flex,
styles.column,
styles.recommendation,
styles.shadow,
index === 0 ? {marginLeft: theme.sizes.margin} : null,
isLastItem ? {marginRight: theme.sizes.margin / 2} : null,
]}>
<ImageBackground
style={[styles.imageback]}
source={{uri: item.preview}}
/>
</View>
<View
style={[
index === 0 ? {marginLeft: theme.sizes.margin - 10} : null,
isLastItem ? {marginRight: theme.sizes.margin / 2} : null,
]}>
<Text
style={{
fontSize: theme.sizes.font * 1.25,
fontWeight: '200',
color: 'white',
marginLeft: 10,
//paddingBottom: 20,
fontFamily: 'Nunito-Bold',
}}>
{item.title}
</Text>
<Text
style={{
color: theme.colors.caption,
marginLeft: 10,
fontFamily: 'Nunito-SemiBold',
}}>
{item.location}
</Text>
</View>
</TouchableOpacity>
);
};
render() {
return (
<ScrollView style={styles.container}>
<BackgroundSvg style={styles.background} />
<ScrollView
style={styles.contentContainer}
showsVerticalScrollIndicator={false}
contentContainerStyle={{paddingBottom: theme.sizes.paddin}}>
{this.renderRecommended()}
{this.renderRecommended2()}
{/* <View style={styles.mainContainerView}>
<TouchableOpacity style={styles.singInButton} gradient>
<Text style={styles.logInText}>
Activate premium subscription
</Text>
</TouchableOpacity>
</View> */}
</ScrollView>
</ScrollView>
);
}
}
Browser.defaultProps = {
destinations: mocks,
reading: readingList,
};
export default Browser;
My code is the one on the top. Just to simplify I am accesing some elements from JSON and I am creating Flatlist based on this. What I want is is to give some of the JSON files a bolean with premium or not and in this way to make some elements available for user or not.
As part of your destinations array, for each object, you can specify a boolean field called isPremiumItem. Your users should have a boolean field like isPremiumUser to show the type of their subscription.
Then in renderRecommended method you can check the user subscription status (isPremiumUser), and also the specific item status (isPremiumItem). Then you can render accordingly.
I'm using react-native-material-menu's popup for showing menu options.
But the issue is, it's not working for multiple scenarios.
I mean when I click on first menu button, the same methods gets triggered and hence the same menu is opened every time.
What should be the better approach for to handle this particular scenario.
_menu = null;
setMenuRef = ref => {
this._menu = ref;
};
hideMenu = () => {
this._menu.hide();
};
showMenu = () => {
this._menu.show();
};
<FlatList
data={this.state.clientsList}
renderItem={({ item }) => {
return (
<View style={styles.caseItem} >
<Card style={styles.card}>
<CardItem>
<Body>
<View style={styles.rowTitle}>
<Text style={styles.title}>{item.FullName}</Text>
<Menu
ref={this.setMenuRef}
button={
<Icon
type="Feather"
name="more-vertical"
onPress={this.showMenu}
style{{fontSize:20,color:'#555'}}
/>
}>
<MenuItem onPress={this.hideMenu}>View</MenuItem>
<MenuItem onPress={this.hideMenu}>Edit</MenuItem>
<MenuItem onPress={this.hideMenu}>Delete </MenuItem>
</Menu>
</View>
<View>
<Text style={styles.lbl}>Email: <Text style={styles.lblValue}>{item.EmailID}</Text></Text>
<Text style={styles.lbl}>Client Type: <Text style={styles.lblValue}>{item.ClientType}</Text></Text>
</View>
</Body>
</CardItem>
</Card>
</View>
);
}}
keyExtractor={item => item.ID}
/>
Snack Here
To handle the states in the correct way, you will need to create a new Class which will be handling just the MenuItem
The below code will work: Here is the Snack.
import * as React from "react";
import { Text, View, StyleSheet } from "react-native";
import Constants from "expo-constants";
import { Container, Content, Card, CardItem, Body, Icon } from "native-base";
import * as Font from "expo-font";
import Menu, { MenuItem, MenuDivider } from "react-native-material-menu";
// You can import from local files
import AssetExample from "./components/AssetExample";
export default class App extends React.Component {
onView = () => {
alert("Do something here");
console.log("You can do what ever you want here");
}
render() {
return (
<View style={styles.container}>
<View style={styles.caseItem}>
<Card style={styles.card}>
<CardItem>
<Body>
<View style={styles.rowTitle}>
<Text style={styles.title}>John Doe</Text>
<CustomMenu onView={this.onView}/>
</View>
<View>
<Text style={styles.lbl}>
Email: <Text style={styles.lblValue}>john#yopmail.com</Text>
</Text>
<Text style={styles.lbl}>
Client Type: <Text style={styles.lblValue}>Individual</Text>
</Text>
</View>
</Body>
</CardItem>
</Card>
</View>
<View style={styles.caseItem}>
<Card style={styles.card}>
<CardItem>
<Body>
<View style={styles.rowTitle}>
<Text style={styles.title}>John Doe</Text>
<CustomMenu onView={this.onView}/>
</View>
<View>
<Text style={styles.lbl}>
Email: <Text style={styles.lblValue}>john#yopmail.com</Text>
</Text>
<Text style={styles.lbl}>
Client Type: <Text style={styles.lblValue}>Individual</Text>
</Text>
</View>
</Body>
</CardItem>
</Card>
</View>
<View style={styles.caseItem}>
<Card style={styles.card}>
<CardItem>
<Body>
<View style={styles.rowTitle}>
<Text style={styles.title}>John Doe</Text>
<CustomMenu onView={this.onView} />
</View>
<View>
<Text style={styles.lbl}>
Email: <Text style={styles.lblValue}>john#yopmail.com</Text>
</Text>
<Text style={styles.lbl}>
Client Type: <Text style={styles.lblValue}>Individual</Text>
</Text>
</View>
</Body>
</CardItem>
</Card>
</View>
</View>
);
}
}
class CustomMenu extends React.Component {
_menu = null;
setMenuRef = ref => {
this._menu = ref;
};
hideMenu = () => {
this._menu.hide();
};
onViewClick = () => {
const {onView} = this.props;
onView();
this.hideMenu();
}
showMenu = () => {
this._menu.show();
};
render() {
return (
<Menu
ref={this.setMenuRef}
button={
<Icon
type="Feather"
name="more-vertical"
onPress={this.showMenu}
style={{ fontSize: 20, color: "#555" }}
/>
}
>
<MenuItem onPress={this.onViewClick}>View</MenuItem>
<MenuItem onPress={this.hideMenu}>Edit</MenuItem>
<MenuItem onPress={this.hideMenu}>Delete </MenuItem>
</Menu>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: "center",
paddingTop: Constants.statusBarHeight,
backgroundColor: "#ecf0f1",
padding: 8
},
rowTitle: {
flexDirection: "row",
justifyContent: "space-between",
width: "100%"
},
title: {
fontSize: 14,
marginBottom: 5
},
lbl: {
fontSize: 11,
color: "#000"
},
lblValue: {
fontSize: 11,
color: "#555",
fontWeight: "normal"
},
caseItem: {
marginBottom: 0
}
});
Since the FlatList will iterate over the menu items, you need to maintain index for each iterable menu options.
You can check, you are passing item object within renderItems prop. So you can use the same item.id as a key to your child (iterable) component.
Since the child component now maintains an index, so now you can pass it in methods which will help you differentiate the event which got triggered from the child element.
I hope this might give you an idea about the issue.
I am trying to create a two column grid using flex. One column will be used to display a word or phrase and the second column will be used to translate the first column. Here is a link: http://imgur.com/nZGo8pb to give you a visual idea on what I am trying to achieve.
I am unable to get two columns side by side. I am only able to have my words appear on top of each other. This is best attempt. A huge failure.http://imgur.com/a/ICApr
My code is:
nent} from 'react';
import { Text, View,StyleSheet,Image,TextInput,ListView} from 'react-native';
class AddWords extends Component{
state = {words:['iku','konkai','kaikan'],
word:'',
EnglishWords:['go','this time','next time']
}
renderList(tasks){
return(
tasks.map((task) =>{
return(
<View key={task} style={styles.item}>
<Text>
{task}
</Text>
<Text>
</Text>
</View>
)
})
)
}
renderEnglishWords(english){
return(
english.map((english) =>{
return(
<View key={english} style={styles.item2}>
<Text>
{english}
</Text>
<Text>
</Text>
</View>
)
})
)
}
addWord(){
let words = this.state.words.concat([this.state.word]);
this.setState({words})
}
render(){
return(
<View style={styles.container}>
<TextInput
style={styles.input}
onChangeText={(word) => {
this.setState({word})
}}
onEndEditing={()=>this.addWord()}
/>
<View style={styles.wordContainer}>
{this.renderList(this.state.words)}
{this.renderEnglishWords(this.state.EnglishWords)}
<View style={styles.item2}>
</View>
</View>
</View>
)
}
}
const styles = StyleSheet.create({
container:{
flex:1,
borderWidth:3,
borderColor:'green',
flexDirection:'column',
paddingTop:10
},
wordContainer:{
flexDirection: 'column',
borderColor:'blue',
borderWidth:2
},
input:{
height:60,
borderWidth:1,
borderRadius:5,
borderColor:'black',
textAlign:'center',
margin:10,
paddingTop:20,
paddingBottom:10
},
item:{
borderColor:'red',
borderWidth:2
},
item2:{
borderColor:'black',
borderWidth:2,
flexDirection:'column',
}
})
export default AddWords;
Any help will be greatly appreciated.
Thanks.
You need to wrap both inner containers in another <View> with the following style:
<View style={styles.container}>
<TextInput
style={styles.input}
onChangeText={(word) => {
this.setState({ word })
}}
onEndEditing={this.addWord}
/>
<View style={{ flexDirection: 'row', flex: 1 }}>
<View style={styles.wordContainer}>
...
</View>
<View style={styles.item2}>
...
</View>
</View>
</View>
It's because the flexDirection in styles.wordContainer is set to 'column', it should be set to 'row'.
Check out this link on flex-direction examples.