How to break line of multiple Text List Items when they exceeds it container size? - react-native

I am developing a react native app. In the app, I have a iterator mapping multiples types that are show inside a View. Each of these types have an specific color, so that is why I have an each tag for each type.
I have made a simplified example what I want and what is happening.
I want when the Text List Items exceeds its container, that they break to a new line. I tried many ways but don't discover how to do it.
The example: https://snack.expo.dev/#anschau/multiple-text-problem-not-breaking-line
The code:
import React from "react";
import { StyleSheet, Text, View } from "react-native";
const LabelTypes = [
{
styleType: "styleType1",
label: "Extensive Type 1",
},
{
styleType: "styleType2",
label: "Another Extensive Type 2",
},
{
styleType: "styleType3",
label: "Type 3",
},
{
styleType: "styleType4",
label: "Type 4",
},
{
styleType: "styleType5",
label: "Type 5",
},
{
styleType: "styleType6",
label: "Type 6",
},
];
const App = () => {
return (
<View style={[styles.container, {
flexDirection: "row"
}]}>
{
LabelTypes.map((item, index) => (
<>
{ index > 0 && <Text> - </Text>}
<Text style={[styles.label, styles[item.styleType] ]}>{item.label}</Text>
</>
))
}
</View>
);
};
const styles = StyleSheet.create({
container: {
maxWidth: "100%",
marginTop: 50,
marginLeft: 20,
marginRight: 20,
borderWidth: 1,
borderColor: "gray"
},
label: {
color: "black",
},
styleType1: {
color: "blue"
},
styleType2: {
color: "red"
},
styleType3: {
color: "green"
},
styleType4: {
color: "orange"
},
styleType5: {
color: "coral"
},
styleType6: {
color: "pink"
},
});
export default App;

Add to your container's (NOT individual labels') style:
flexWrap: 'wrap'
This will simply let items fill the container's width and fall into a new line when it doesn't fit.

Related

I am trying to show scroll indicator in bottom when get to limit

I am trying to show the bottom indicator and then show more data when it reach the limit, I need only to know what the name of the footer indicator in ScrollView in react native
I am trying to show the bottom indicator and then show more data when it reach the limit, I need only to know what the name of the footer indicator in ScrollView in react native
`
import React, { Component } from "react";
import { Text, Button, View, StyleSheet, ScrollView } from "react-native";
class App extends Component {
state = {
// Sample data
items: [
{ item: "Item 1", price: "10", id: 1 },
{ item: "Item 2", price: "20", id: 2 },
{ item: "Item 3", price: "30", id: 3 },
{ item: "Item 4", price: "40", id: 4 },
{ item: "Item 5", price: "50", id: 5 },
{ item: "Item 6", price: "60", id: 6 },
{ item: "Item 7", price: "70", id: 7 },
{ item: "Item 8", price: "80", id: 8 },
{ item: "Item 9", price: "90", id: 9 },
{ item: "Item 10", price: "100", id: 10 },
{ item: "Item 11", price: "110", id: 11 },
{ item: "Item 12", price: "120", id: 12 },
{ item: "Item 13", price: "130", id: 13 },
{ item: "Item 14", price: "140", id: 14 },
{ item: "Item 15", price: "150", id: 15 },
],
};
render() {
return (
<View style={styles.screen}>
<ScrollView> // use of ScrollView Component
{this.state.items.map((item, index) => (
<View key={item.id}>
<View style={styles.summary}>
<Text style={styles.summaryText}>
{item.item} <Text style={styles.amount}>
${item.price}</Text>
</Text>
<Button title="Order" color="#FFC107"
onPress={() => { }} />
</View>
</View>
))}
</ScrollView>
</View>
);
}
}
// Screen styles
const styles = StyleSheet.create({
screen: {
margin: 20,
},
summary: {
flexDirection: "row",
alignItems: "center",
justifyContent: "space-between",
marginBottom: 20,
padding: 10,
shadowColor: "black",
shadowOpacity: 0.26,
shadowOffset: { width: 0, height: 2 },
shadowRadius: 8,
elevation: 5,
borderRadius: 10,
backgroundColor: "white",
},
summaryText: {
fontFamily: "openSansBold",
fontSize: 18,
},
amount: {
color: "#C2185B",
},
});
export default App;
`
For illustration it is better to for provide an example.
import React, { Component } from "react";
import { Text, Button, View, StyleSheet, ScrollView, ActivityIndicator } from "react-native";
class TestScreen extends Component {
state = {
items: [...],
loading: false
};
isCloseToBottom = ({layoutMeasurement, contentOffset, contentSize}) => {
let paddingToBottom = 20;
return layoutMeasurement.height + contentOffset.y >= contentSize.height - paddingToBottom;
};
render() {
return (
<View style={styles.screen}>
<ScrollView
onScroll={({nativeEvent}) => {
//Check whether the scrollview is reaching bottom
if (this.isCloseToBottom(nativeEvent)) {
this.setState({loading: true});
}
}}
scrollEventThrottle={400}
>
{...Your Map Function}
{
this.state.loading && <ActivityIndicator />
}
</ScrollView>
</View>
);
}
}
It is better to implement this kind of list in a FlatList, but it is up to you. Enjoy :)
Edit: added FlatList Component for your reference
<FlatList
keyExtractor={item => item.id}
data={this.state.items}
onEndReached={()=>{
this.setState({loading: true});
}}
renderItem={({item, index}) => {
return(
<View key={item.id}>
<View style={styles.summary}>
<Text style={styles.summaryText}>
{item.item} <Text style={styles.amount}>
${item.price}</Text>
</Text>
<Button title="Order" color="#FFC107"
onPress={() => { }} />
</View>
</View>
)
}}
ListFooterComponent={()=>{
return (this.state.loading && <ActivityIndicator />)
}}
/>

Adding data to FlatList clears the whole list

I am new to react-native. I have a flatlist, that takes data from "state". This works. Then, I added a new function in order to add new data to the flatlist (additionally to the existing data).
As soon as I click on the "delete" button ( don't mind the name) the data of the flatlist is being deleted completely. I want the output to be like
Object 1
Object 2
Object 3 (has been added after button click)
What am I doing wrong? Can you please explain me the reason?
EDIT: I get this warning, but no error.
VirtualizedList: missing keys for items, make sure to specify a key or
id property on each item or provide a custom keyExtractor.,
import React, { Component } from "react";
import { Text, View, StyleSheet, Button, FlatList } from "react-native";
class App extends Component {
state = {
counter: 0,
initialElements: [
{ id: "0", text: "Object 1" },
{ id: "1", text: "Object 2" },
],
};
render() {
const currentCounter = this.state.counter;
const exampleState = this.state.initialElements;
const addElement = () => {
let newArray = [...exampleState, { id: "2", text: "Object 3" }];
this.setState({
initialElements: [newArray],
});
};
return (
<View style={styles.container}>
<View style={styles.counter}>
<Text style={styles.textStyle}>{currentCounter}</Text>
</View>
<View style={styles.deleteButton}>
<Button
title="Hello"
onPress={() =>
this.setState({
counter: currentCounter + 1,
})
}
></Button>
<View style={styles.space}></View>
<Button title="Delete" onPress={addElement}></Button>{" "}
{/* as soon as I click here, the content of the list is being deleted */}
</View>
<FlatList
style={styles.listStyle}
key={(item) => item.id}
data={exampleState}
renderItem={(item) => <Text>{item.item.text}</Text>}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
backgroundColor: "#fff",
justifyContent: "center",
flex: 1,
flexDirection: "column",
alignItems: "center",
},
counter: {
flexDirection: "row",
justifyContent: "center",
},
deleteButton: {
flexDirection: "row",
margin: 5,
marginTop: 100,
},
space: {
width: 5,
height: 5,
},
textStyle: {
margin: 80,
fontSize: 100,
},
listStyle: {
flexDirection: "column",
},
item: {
padding: 10,
fontSize: 18,
height: 44,
},
});
export default App;
I fixed it by changing the addElement to function to:
const addElement = () => {
var newArray = [...exampleState, {id : 2, text : "Object 3"}];
this.setState( {
initialElements: newArray
});
}
So, basically I changed
initialElements: [newArray]
to
initialElements: newArray
because newArray is already an Array, so no need to wrap it again.

how to display item selected from searchable dropdown in react native?

I want year to be displayed on selection from dropdown list.
In this, selected item is being shown as alert I want to set text to the search box.
Here is the code:
import React, { useState, useEffect } from "react";
import {
StyleSheet,
SafeAreaView,
Text,
View,
TextInput,
Image,
Button,
FlatList,
TouchableOpacity,
} from "react-native";
import SearchableDropdown from "react-native-searchable-dropdown";
const years = [
{ id: 1, name: "2021" },
{ id: 2, name: "2020" },
{ id: 3, name: "2019" },
{ id: 4, name: "2018" },
{ id: 5, name: "2017" },
{ id: 6, name: "2016" },
{ id: 7, name: "2015" },
];
export default function Year() {
console.log("App Executed");
return (
<SafeAreaView>
<Text style={styles.headingText}>Select Year</Text>
<SearchableDropdown
onTextChange={(text) => console.log(text)}
// On text change listner on the searchable input
onItemSelect={(year) => alert(JSON.stringify(year))}
// onItemSelect called after the selection from the dropdown
containerStyle={{ padding: 5 }}
// suggestion container style
textInputStyle={{
// inserted text style
padding: 12,
borderWidth: 1,
borderColor: "#ccc",
backgroundColor: "#FAF7F6",
}}
itemStyle={{
// single dropdown item style
padding: 10,
marginTop: 2,
backgroundColor: "#FAF9F8",
borderColor: "#bbb",
borderWidth: 1,
}}
itemTextStyle={{
// text style of a single dropdown item
color: "#222",
}}
itemsContainerStyle={{
// items container style you can pass maxHeight
// to restrict the items dropdown hieght
maxHeight: "50%",
}}
items={years}
// mapping of item array
defaultIndex={"eg:2021"}
// default selected item index
placeholder="eg:2021"
// place holder for the search input
resetValue={false}
// reset textInput Value with true and false state
/>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "white",
padding: 10,
},
titleText: {
padding: 8,
fontSize: 16,
textAlign: "center",
fontWeight: "bold",
},
headingText: {
padding: 10,
},
});
I was unable to use state
here is the solution
const years = [
{ id: 1, name: "2021" },
{ id: 2, name: "2020" },
{ id: 3, name: "2019" },
{ id: 4, name: "2018" },
{ id: 5, name: "2017" },
{ id: 6, name: "2016" },
{ id: 7, name: "2015" },
];
export default function Year() {
const [selectedItems, setSelectedItems] = useState();
console.log("App Executed");
return (
<SafeAreaView>
<SearchableDropdown
onTextChange={(text) => console.log(text)}
// On text change listner on the searchable input
selectedItems={selectedItems}
onItemSelect={(year) => setSelectedItems(year)}
// onItemSelect called after the selection from the dropdown
containerStyle={{ padding: 5 }}
// suggestion container style
textInputStyle={{
// inserted text style
padding: 12,
borderWidth: 1,
borderColor: "#ccc",
backgroundColor: "#FAF7F6",
}}
itemStyle={{
// single dropdown item style
padding: 10,
marginTop: 2,
backgroundColor: "#FAF9F8",
borderColor: "#bbb",
borderWidth: 1,
}}
itemTextStyle={{
// text style of a single dropdown item
color: "#222",
}}
itemsContainerStyle={{
// items container style you can pass maxHeight
// to restrict the items dropdown hieght
maxHeight: "50%",
}}
items={years}
// mapping of item array
defaultIndex={"eg:2021"}
// default selected item index
placeholder="eg:2021"
// place holder for the search input
resetValue={false}
// reset textInput Value with true and false state
/>
</SafeAreaView>
);
}
I SLOVED THAT BY THIS TRICK WAY:
const getTypeNameById_func = async id => {
const dataa = await accountsType.find(item => {
if (item.ID == id)
return item.NAME;
});
setTextSearchable(dataa.NAME);
};
AND IN SEARCHABLE DROPDOWN :
<SearchableDropdown
items={filterData}
placeholder={String(**textSearchable**)}
resetValue={false}
underlineColorAndroid="transparent"
onTextChange={text => console.log(text)}
onItemSelect={item => {
getTypeNameById_func(item.id);
setAccountType(item.id);
}}
defaultIndex={1}
/>
u can use useState variable and pass that variable in placeholder like:-
placeholder={variableName}

React Native - Search an array off Object using react hooks

I have an array off Object inside a variable named data.
The array looks like this:
const data = [
{
"id": "0.804802585702977",
"value": "Bar",
},
{
"id": "0.9359341974615858",
"value": "Mar",
},
{
"id": "0.4182922963461958",
"value": "Naba",
},
{
"id": "0.6132336648416628",
"value": "Socerr",
},
{
"id": "0.060587558948085984",
"value": "Mall",
},
]
I want to create a search bar to search all the value inside that array and if the search text is equal to the value inside that array the user will be able to see that value?
Please help?
You need to use filter function to search/Sort data from Array. Please check following it may solve you problem.
import React, { useState } from "react";
import { Text, TextInput, View, StyleSheet } from "react-native";
import Constants from "expo-constants";
// You can import from local files
import AssetExample from "./components/AssetExample";
// or any pure javascript modules available in npm
import { Card } from "react-native-paper";
const data = [
{
id: "0.804802585702977",
value: "Bar",
},
{
id: "0.9359341974615858",
value: "Mar",
},
{
id: "0.4182922963461958",
value: "Naba",
},
{
id: "0.6132336648416628",
value: "Socerr",
},
{
id: "0.060587558948085984",
value: "Mall",
},
];
export default function App() {
let [filteredData, setFilteredData] = useState(data);
function _searchFilterFunction(searchText, data) {
let newData = [];
if (searchText) {
newData = data.filter(function(item) {
const itemData = item.value.toUpperCase();
const textData = searchText.toUpperCase();
return itemData.includes(textData);
});
setFilteredData([...newData]);
} else {
setFilteredData([...data]);
}
}
return (
<View style={styles.container}>
<Text style={styles.paragraph}>Search Here.</Text>
<TextInput
style={styles.input}
underlineColorAndroid="transparent"
placeholder="Search"
placeholderTextColor="#9a73ef"
autoCapitalize="none"
onChangeText={(value) => {
_searchFilterFunction(value, data);
}}
/>
{filteredData.map((item, index) => {
return <Text style={styles.paragraph}>{item.value}</Text>;
})}
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
paddingTop: Constants.statusBarHeight,
backgroundColor: "#ecf0f1",
padding: 8,
},
input: {
margin: 15,
height: 40,
paddingLeft: 10,
borderRadius: 2,
borderColor: "#7a42f4",
borderWidth: 1,
},
paragraph: {
margin: 24,
fontSize: 18,
fontWeight: "bold",
textAlign: "center",
},
});

Is it possible to dynamically create components in React Native?

Is it possible to dynamically create and add view components in React Native?
For example, firstly I have only empty screen and information of all views come from server in JSON, and then it is need to generate them on the screen.
For example - application getting json from server. This json describes the screen that have to be builded:
{
"type": "linearlayout",
"subviews": [{
"type": "text",
"fields": {
"text": "This is text field"
},
"styles": {
"color": "",
"textSize": 14
}
}, {
"type": "button",
"fields": {
"text": "JUST BUTTON"
},
"transition": {
"name": "http://www.link.com"
}
}, {
"type": "text",
"fields": {
"text": "This is another text field"
},
"styles": {
"color": "",
"textSize": 18
}
}]
}
So, by that JSON I need dynamically views building in React Native. But I can't see any ability to write JS code inside JSX - only static views and dynamically changing of props
Yes this is possible. Assume that you retrieve your JSON data successfully and save it to some state then in your render function you can use it like that;
render() {
var productList = [];
this.state.data.products.forEach(function (tmpProduct) {
productList.push(
<View style={cardView} key={tmpProduct.id}>
<Grid style={upperGrid}>
<Col style={{flex: 0.5}}>
<Thumbnail
source={require('../../../images/sample-image.png')}
style={itemThumb}>
</Col>
<Col>
<Text style={cardItemHeader} numberOfLines={2}>{tmpProduct.title}</Text>
<Text style={cardItemBody} numberOfLines={2}>{tmpProduct.description}</Text>
</Col>
</Grid>
</View>
);
}.bind(this));
return (
<Container theme={theme}>
<Image source={require('../../../images/grad-bg.png')} style={background} >
<Content style={scrollContent}>
{productList}
</Content>
</Image>
</Container>
)
}
I hope this code piece give you an idea. You can adapt it to your case.
React docs (and by extension it could be done with ReactNative too) show how to choose the component type at runtime:
import React from 'react';
import { PhotoStory, VideoStory } from './stories';
const components = {
photo: PhotoStory,
video: VideoStory
};
function Story(props) {
const SpecificStory = components[props.storyType];
return <SpecificStory story={props.story} />;
}
Doing so, you could just only need to walk on your JSON tree and just create the ReactNative components, using the components object as a mapping between the type defined in the JSON tree and their constructors.
Here is another approach:-
import { StatusBar } from 'expo-status-bar';
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
const renderObject = {
type : "View",
children : [
{
type: "View",
styles: {
backgroundColor: "orange",
flex:1,
justifyContent:"center",
alignItems: "center"
},
children: [
{
type: "Text",
styles: {
color: "yellow",
fontSize: 20
},
text: "Hello"
},
{
type: "View",
styles: {
backgroundColor: "red",
width: 100,
height: 5,
marginTop: 10
},
children: []
}
]
},
{
type: "View",
styles: {
flex:1,
justifyContent:"center",
alignItems: "center"
},
children: [
{
type: "Text",
styles: {
color: "red",
fontSize: 40
},
text: "Hello"
}
]
},
{
type: "View",
styles: {
flex:1,
justifyContent:"center",
alignItems: "center",
backgroundColor: "green"
},
children: [
{
type: "Text",
styles: {
color: "white",
fontSize: 80
},
text: "Hello"
}
]
}
],
styles: {
flex:1
}
}
const CustomComp = (props) => {
const {type} = props;
if(type == "View"){
const {styles, children} = props;
return <View style={styles}>{children.map((item) => CustomComp(item))}</View>
} else if(type == "Text") {
const {styles, text} = props;
return <Text style={styles} >{text}</Text>
}
}
export default function App() {
return (
<View style={styles.container}>
{CustomComp(renderObject)}
<StatusBar style="auto" />
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
justifyContent: 'center',
},
});
You can find the full code on this Repo.
Yes it is possible to dynamically create components in React Native based on data you retrieve from the server.
However, if you are wanting the app to check for the latest JS code (including new components/views) without requiring an update through app store, you could use something like code-push. https://microsoft.github.io/code-push/
Your question is somewhat vague so if I misunderstood then possibly you could give an example 'information of all views'.
One of the benefits of using react native (vs webview) is that your users won't be staring at empty screens when the app is loading data. If you return all views from server, then it works like web page. I have done something like that before. Believe me that's not the best UX. Ideally json response should only return data. Then client can be built with any framework (react native, iOS or Android native) and they share the same API endpoints.