Trying to create two columns in react-native - javascript

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.

Related

React Native flatlist takes a while to update items

So i am currently making a messaging application and this needs to be able to live messages, I am using a flat list to display these items and everytime i append an item to the messageFetch it takes ages for the flat list to load, (at any time there could be 100's to 1000's of items in the list). How can I speed this up? Also the components are of diffrent sizes.
flatlist component:
<View style={styles.container}>
<View style={styles.topBar} focusable>
<Text style={{ fontFamily: "Roboto-Regular", fontSize: 17, color: "white" }}>{name}</Text>
</View>
<View style={styles.mainChat} focusable>
<View style={[styles.loading, { display: loadedFinished ? "none" : "flex" }]}>
<ActivityIndicator style={[styles.loading, { display: loadedFinished ? "none" : "flex" }]} />
</View>
<FlatList
inverted
ref={list}
data={messageFetch.reverse()}
renderItem={Message}
keyExtractor={(item) => item.index}
/>
</View>
</View>
loadedFinished only runs once and stops at about 3 seconds.
Message Component:
function Message({ item }) {
if (item.embed.type != undefined) {
return <Text>hello<Text>
}
return (
<View style={[mesgStyles.mainMessage, { flexDirection: item.original ? "row-reverse" : "row" }]}>
<Image style={mesgStyles.userPfp} resizeMode="contain" source={{ uri: item.pfp }}></Image>
<View style={mesgStyles.spacer} />
<View style={mesgStyles.messageBody}>
<Text style={mesgStyles.mainText}>{item.text}</Text>
</View>
</View>
);
}
Any help would be greatly appreciated. Thanks

A table using map function

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.

React Native TextInput Value persist when Tab is changed

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

Multiple Component with Same Function Name in React Native

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.

Big margin between row direction on layout

i'm having trouble formatting one of my screens.
I want to place 3 textinputs in a row, and right below them a button and a checkbox, there's a picture below for more details (it's a crossed box and a question mark as of now, don't mind it i'll fix it later). But i'm getting a huge unwanted margin between the two rows, and i can't get rid of it.
This is the code
<View style = {styles.container}>
<View style={styles.rowInit2}>
<View style={{flex:1}}>
<TextInput style ={styles.input}
maxLength={25}
onChangeText={UserEmail => this.setState({UserEmail})}
placeholder = 'Item'
underlineColorAndroid='rgba(0,0,0,0.1)'/>
</View>
<View style={{flex:1}}>
<TextInput style ={styles.input2}
maxLength={3}
onChangeText={UserEmail => this.setState({UserEmail})}
placeholder = 'Cantidad'
underlineColorAndroid='rgba(0,0,0,0.1)'/>
</View>
<View style={{flex:1}}>
<TextInput style ={styles.input2}
maxLength={5}
placeholder = 'Precio'
onChangeText={UserEmail => this.setState({UserEmail})}
underlineColorAndroid='rgba(0,0,0,0.1)'/>
</View>
</View>
<View style = {styles.row}>
<View style={{flex:1}}>
<CheckBox
checkedIcon={() => {return (<Icon type='feather' name= 'check' />)}}
uncheckedIcon={() => {return (<Icon type='feather' name= 'check' />)}}
checked={this.state.checked}
onPress={() => this.setState({checked: !this.state.checked})}
containerStyle={{backgroundColor:'transparent', width:'20%'}}
/>
</View>
<View style={{flex:1}}>
<Icon
containerStyle ={styles.iconStyle}
name= 'add-circle'
color='#0419ba'
onPress={() => console.log('hello')}
/>
</View>
</View>
</View>
and this is the css
export default{
container:{
flex:1,
backgroundColor:'#fff'
},
itemVendido:{
color:'tomato',
fontWeight:'500',
},
rowInit2:{
flex: 1,
flexGrow: 1,
width:'100%',
marginTop:'5%',
justifyContent:'space-between',
flexDirection:'row',
padding:'2%',
},
input:{
width:'90%',
borderRadius: 25,
backgroundColor: 'rgba(0,0,0,0)',
fontSize:16,
},
input2:{
width:'65%',
borderRadius: 25,
backgroundColor: 'rgba(0,0,0,0)',
fontSize:16,
},
row:{
flex: 1,
flexGrow: 1,
width:'100%',
justifyContent:'space-between',
flexDirection:'row',
padding:'2%',
},
iconStyle:{
fontSize:30,
padding:'3%',
},
}
this is how it looks like
thanks in advance!
I just created a new container using flexShrink:1
Thanks anyway!

Categories

Resources