How to add space between components that comes from a mapping function? - react-native

I am trying to add some buttons with a title that is inside every position of an array (for exaMple the first button have its title in the content of the array in the position 0), that is the reason i am using a map function and it works but... i can not add space between each button
it looks like this:
THIS IS WHERE THE MAPPING FUNCTION IS CALLED:
<ScrollView horizontal={true} showsHorizontalScrollIndicator={false}>
<View style={{
flexDirection: 'row',
justifyContent: 'space-between'}}>
{mapping()}
</View>
</ScrollView>
THIS IS THE FUNCTION:
function mapping() {
const horas = ["6:30-7:30", "7:30-8:30", "7:30-8:30"...]
const mappeo = horas.map((i) => {
return (
<Button
title={i}
type="outline"
style={{ padding:10}}/>
)
}
)
return (mappeo)
}
So how can i separate the buttons?

How about using margin. Padding are used for content inside a container and margins are used for applying margins or spaces outside the container.
Try this
function mapping() {
const horas = ["6:30-7:30", "7:30-8:30", "7:30-8:30"...]
const mappeo = horas.map((i) => {
return (
<Button
title={i}
type="outline"
style={{ padding:10, marginHorizontal:10}}/>
)
}
)
return (mappeo)
}

add 'marginHorizontal' to your button like below:
function mapping() {
const horas = ["6:30-7:30", "7:30-8:30", "7:30-8:30"...]
const mappeo = horas.map((i) => {
return (
<Button
title={i}
type="outline"
style={{ padding:10, marginHorizontal: 5 }}/>
)
}
)
return (mappeo)
}

Related

Component only reachable by scrolling regardless of window size

I'm trying to make a layout so that the later parts of the view are only reachable by scrolling.
Currently I'm using Dimensions to generate Views with the correct height. Is there a better way of doing so? My current solution doesn't seem too correct.
export default function MyApp() {
const height = Dimensions.get('window').height;
return (
<View style={styles.container}>
<ScrollView>
<View style={{backgroundColor: 'green', height:height}}/>
<View style={{backgroundColor: 'red', height:40}}/>
</ScrollView>
</View>
);
}
const styles = StyleSheet.create({
container:{
backgroundColor: 'white',
flex: 1
}
});
You can use VirtualizedList component, for example as
<VirtualizedList
data={['body']}
renderItem={({ item }) => (
<View style={styles.screen}>
{/* Put more content for body */}
</View>
)}
keyExtractor={(item, index) => index.toString()}
getItemCount={() => {
return 1;
}}
getItem={(data, index) => {
return data[index];
}}>
</VirtualizedList>
Your solution work, but not good and it have downside, when you change your phone orientation to landscape there will be bug. I dont like using Dimensions in my code unless there is no other way or use Dimensions addEventListener to listen window size and update component whenever window size change. I will suggest you a better way.
First, create a component called LayoutSizeAwareView, after this view rendered, we will catch it size from onLayout props and use them to render it children.
const LayoutSizeAwareView = (props) => {
const [size, setSize] = React.useState({width: 0, height: 0});
return (
<View
...props,
onLayout={(e) => {
setSize({
width: e.nativeEvent.layout.width,
height: e.nativeEvent.layout.height,
})
props.onLayout(e)
}}
>
{props.children(size)}
</View>
)
}
And then, in your case, use it like this
export default function MyApp() {
return (
<LayoutSizeAwareView style={styles.container}>
{({width, height}) => {
return (
<ScrollView>
<View style={{backgroundColor: 'green', height: height}}/>
<View style={{backgroundColor: 'red', height: 40}}/>
</ScrollView>
)
}}
</View>
);
}
const styles = StyleSheet.create({
container:{
backgroundColor: 'white',
flex: 1
}
});
This way your code look even cooler, there will be some typo in my code since I dont have IDE here, but you might get the idea.

React Native stored array data with asyncstorage returns nothing

I am trying to build a lunch picker app that allows user to add their own menu. I want to save user data into array by using AsyncStorage. However, my value returns nothing even though the array has values. Below is my code.
//Main screen
class HomeScreen extends React.Component {
//initial
constructor(props) {
super(props);
this.state = {
isReady: false,
myMenu: '????',
menutext: '',
randomArray: ['a', 'b', 'c'],
visibility: false,
};
}
_loadMenu = async () => {
try{
const loadMenu = await AsyncStorage.getItem("menuInStorage")
const parsedLoadMenu = JSON.parse(loadMenu)
const myReturn = [...this.state.randomArray, parsedLoadMenu]
this.setState({randomArray: myReturn})
}
catch(err){
alert(err)
}
}
//get input from textinput field and add to array
addMenu = newMenu => {
//...
this._saveMenu(this.state.randomArray)
};
_saveMenu = (saving) => {
const saveMenu = AsyncStorage.setItem("menuInStorage", JSON.stringify(saving))
}
//control modal
setModalVisibility(visible) {
this.setState({visibility: visible});
}
//UI
render() {
return (
<View style={styles.mainContainer}>
<View style={[styles.container, {flexDirection: 'row', justifyContent: 'center'}]}>
<TextInput
style={{ height: 40, fontSize: 20, paddingLeft: 15, textAlign: 'left', width: 250, borderBottomColor: '#D1D1D1', borderBottomWidth: 1 }}
placeholder=".."
onChangeText={menutext => this.setState({ menutext })}
value={this.state.menutext}
/>
<Button
title=".."
onPress={() => this.addMenu(this.state.menutext)}
buttonStyle={{width:100}}
backgroundColor="#2E282A"
/>
</View>
<Text>{'\n'}</Text>
<Button
onPress={() => this.setModalVisibility(true)}
title=".."
buttonStyle={{width: 150}}
backgroundColor="#2E282A"
/>
</View>
<Modal
onRequestClose={() => this.setState({ visibility: false })}
animationType={'slide'}
transparent={false}
visible={this.state.visibility}
>
<View style={[styles.modalContainer, {marginBottom: 100}]}>
<Text style={[styles.text, { fontWeight: 'bold', padding: 20, backgroundColor: '#9090DA', borderBottomColor: '#5C5C8B',
borderBottomWidth: 1,}]}>
{'<'}List will be here{'>'}
</Text>
<ScrollView style={{height: "94%"}}>
<View style={styles.row}>{this.state.randomArray}</View>
</ScrollView>
<Button
buttonStyle={{justifyContent: 'center', marginTop: 5}}
backgroundColor="#2E282A"
onPress={() => this.setModalVisibility(!this.state.visibility)}
title="Close"
/>
</View>
</Modal>
</View>
);
}
}
How the app supposed to work is, when user clicks a button, the modal shows all data in array called 'randomArray'. After user added their custom text, it should be added at the end of the randomArray. I want to save this data to the disk and load from the disk when the app is launched. At this moment, I can load array data, but it doesn't keep user data. My current code returns nothing. I need your help. Thanks.
It looks like the logic in _loadMenu is slightly incorrect on this line:
const myReturn = [...this.state.randomArray, parsedLoadMenu]
If I understand correctly, you're expecting parsedLoadMenu to be a value of type Array. The line above will basically append the value parsedLoadMenu to the resulting array stored in myReturn - in the case of your code, this will mean the last item of myReturn will be an array, which would be incorrect from what I see in your code. Consider updating this line as shown:
/*
Add ... before parsedLoadMenu to concatenate the two arrays in myReturn
*/
const myReturn = [...this.state.randomArray, ...parsedLoadMenu]
By adding the ... as shown, this causes the two arrays this.state.randomArray and parsedLoadMenu to be concatenated together in myReturn. It would also be worth checking the parse result from JSON.parse() to ensure that it is an array before attempting this concatenation:
_loadMenu = async () => {
try{
const loadMenu = await AsyncStorage.getItem("menuInStorage")
let parsedLoadMenu = JSON.parse(loadMenu)
/*
Consider an additional check here to ensure the loaded data is of
correct Array type before proceeding with concatenation
*/
if(!Array.isArray(parsedLoadMenu)) {
parsedLoadMenu = [];
}
/* Concatenate the two arrays and store result in component state */
const myReturn = [...this.state.randomArray, ...parsedLoadMenu]
this.setState({randomArray: myReturn})
}
catch(err){
alert(err)
}
}
Also, consider revising the addMenu logic, so that the entire array of menu items in your is persisted to AsyncStorage rather than the newly added menu item only, as you are currently doing:
addMenu = (newMenu) => {
/*
Persist current randomArray with newMenu item appended
*/
this._saveMenu([...this.state.randomArray, newMenu])
};
Hope this helps!

How to use checkbox in loop in react naive

How to use checkbox in loop with diffrent key when i use in loop and click on any one after than check all loop checkbox give me solution
You can create an array of solutions in state:
...
state.solutions = [
{value:false},
{value:false},
{value:false}
]
Create a changes event handler:
changeEvent = (ev, index) => {
let tmp_solution = [...state.solutions];
tmp_solutions[index].value = !tmp_solutions[index].value;
this.setState({solutions: tmp_solution})
}
Create the checkboxes render function:
const checkBoxes = this.state.solutions.map((index) =>{
return(
<CheckBox
value={this.state.solutions[index].value}
onValueChange={(ev) => this.changeEvent(ev, index)} key={index}
/>
)
});
Render all the checkboxes:
render() {
<View>
{checkBoxes}
</View>
}
...
sorry if there are errors
Well, suppose that you have a data, so you can use map to do that. In order to save the answers also you can use index in setSetate as below. I use the react-native-checkbox-heaven component to have the check Box:
import CheckBox from 'react-native-checkbox-heaven';
renderContentCheckBox=()=>{
console.log("[renderContent] your data", this.state.data);
return Object.keys(this.state.data).map(function (item, index) {
return (<View key={index} style={{ alignItems: 'flex-start', justifyContent: 'flex-start', width: Dimensions.get('window').width / 1.1, }}>
<CheckBox
label={item.title}
labelStyle={styles.labelStyle}
iconSize={28}
iconName='matMix'
checked={this.state.check1}
checkedColor='#44FF00'
uncheckedColor='#FFFFFF'
onChange={(val) => {(value) => { that.setState({ ["CheckBox" + index]: value, }); console.log("radio" + index, value);
}}
/>
</View>
);
}
}
Then you can use it inside the render:
render() {
return (<View>
{this.renderContentCheckBox(this)}
</View>
);
}

React-native FlatList item changes position after update

I have created a flatlist and each item has a button that onPress will change item value. The issue comes up when I change item value, as that item will also unexpectedly fall down to the last position of the flatlist.
This is happening only from React-Native version 57 +
The 55.4 version didnt' run into this problem, but I need to upgrade react-native to 57+.
Thanks in advance for any help :)
Here is the sample code:
import React, { Component } from 'react';
import { View, Text, FlatList, StyleSheet, Button } from 'react-native';
class List extends Component {
state = {
currencies: {
USD: 0,
EUR: 0,
GBP: 0,
BTC: 0,
CNY: 0,
AUD: 0,
JPY: 0
}
}
render() {
return (
<View style={styles.container}>
<FlatList
extraData={this.state}
data={Object.keys(this.state.currencies)}
style={{ flex: 1 }}
renderItem={({ item }) => (
<Row
itemValue={this.state.currencies[item]}
itemName={item}
numberUp={(name) => this.setState({currencies:
{...this.state.currencies,
[name] : this.state.currencies[name] + 1}
})
}
/>
)}
/>
</View>
)
}
}
const styles = StyleSheet.create({
container: {
flexDirection: "row",
},
itemContainer : {
flexDirection: "row",
justifyContent: "center",
margin: 10
},
itemText : {
fontSize: 30
}
});
export default List;
const Row = (props) => (
<View style={styles.itemContainer}>
<Text style={styles.itemText}>{props.itemName} </Text>
<Text style={styles.itemText}>{props.itemValue} </Text>
<Button title="PLUS" onPress={() => props.numberUp(props.itemName)}/>
</View>
);
you are trying to append item into the list. that's why it is displaying item at the end of the list.
try below code, I have tried it and it's working:
render() {
return (
<View style={styles.container}>
<FlatList
extraData={this.state}
data={Object.keys(this.state.currencies)}
style={{ flex: 1 }}
renderItem={({ item }) => (
<Row
itemValue={this.state.currencies[item]}
itemName={item}
numberUp={(name) => {
let currencyList = this.state.currencies;
currencyList[name] = this.state.currencies[name] + 1;
this.setState({currencies: currencyList})
}
}
/>
)}
/>
</View>
)
}
Object doesn't maintain the property order. Thats why order gets changed in your list when you update it. ECMA script defines object as
An object is a member of the type Object. It is an unordered
collection of properties each of which contains a primitive value,
object, or function. A function stored in a property of an object is
called a method.
So to maintain the order its better to use an array instead.
currencies: [
{currency:USD, value:0},
{currency:EUR, value:0},
{currency:GBP, value:0},
{currency:BTC, value:0},
{currency:CNY, value:0},
{currency:JPY, value:0},
]

React Native Tab View : How to change text color on change of tab

I am using react-native-community/react-native-tab-view
is there any method to change the tab text color on change of tab.Right now its just lighten the text color but wanted to change it to a different color ?
To change the text color on your TabBar, it should look like this:
<TabBar
{...props}
indicatorStyle={{ backgroundColor: '#eeaf3b' }}
style={{ backgroundColor: '#282828', height: 55 }}
indicatorStyle={{ backgroundColor: '#eeaf3b', height: 5 }}
renderLabel={this.renderLabel} />
Then renderLabel function should look like this:
renderLabel = ({ route, focused, color }) => {
return (
<View>
<Text
style={[focused ? styles.activeTabTextColor : styles.tabTextColor]}
>
{route.title}
</Text>
</View>
)
}
Then your style should look like this:
const styles = StyleSheet.create({
activeTabTextColor: {
color: '#eeaf3b'
},
tabTextColor: {
color: '#ccc'
}
})
In that case, try passing a callback to the renderLabel property in your TabView like so:
_renderLabel = (scene) => {
const myStyle = { /* Defined your style here.. */ }
// grab the label from the scene. I'm not really sure
// about the structure of scene, but you can see it using console.log
const label = scene.label
return (
<Text style={myStyle}>{label}</Text>
);
}
_renderHeader = () => {
return <TabBar renderLabel={this._renderLabel} />
}