I have a SectionList in the Support.js:
import React, {useState} from 'react';
import { StyleSheet, View, Text, Dimensions, StatusBar, SectionList, Pressable, Linking } from 'react-native';
import { DrawerActions } from '#react-navigation/native';
import MaterialIcon from 'react-native-vector-icons/MaterialIcons';
import Feather from 'react-native-vector-icons/Feather';
import Main from './Main'
import SearchBar from './SearchBar';
const WINDOW_HEIGHT = Dimensions.get('window').height;
const DATA = [
{
title: "Stanbul",
data: [<Text onPress={()=>{Linking.openURL('tel:Phone number');}}>Phone number</Text>]
},
{
title: "Antalya",
data: [<Text onPress={()=>{Linking.openURL('tel:Phone number');}}>Phone number</Text>]
},
{
title: "Rome",
data: [<Text onPress={()=>{Linking.openURL('tel:Phone number');}}>Phone number</Text>]
},
{
title: "Milano",
data: [<Text onPress={()=>{Linking.openURL('tel:Phone number');}}>Phone number</Text>]
}
];
const Item = ({ title }) => (
<View style={styles.item}>
<Text style={styles.title}>{title}</Text>
</View>
);
export default function Support({ navigation }) {
const [searchPhrase, setSearchPhrase] = useState("");
const [clicked, setClicked] = useState(false);
(item.toUpperCase().includes(searchPhrase.toUpperCase().trim().replace(/\s/g, ""))) {
return <Item title={item}/>;
}
};
return(
<View style={styles.mainContainer}>
<StatusBar backgroundColor={'#fdf38a'} barStyle='dark-content'/>
<View style={styles.appBar}>
<MaterialIcon name="menu" size={32} color="#2e2a00" backgroundColor={'none'} onPress={() => navigation.dispatch(DrawerActions.openDrawer())}/>
<Text style={styles.appBarText}>Support</Text>
<Feather name="x" size={32} color="#2e2a00" backgroundColor={'none'} onPress={() => navigation.navigate(Main)}/>
</View>
<View style={styles.mainContent}>
<SearchBar
searchPhrase={searchPhrase}
setSearchPhrase={setSearchPhrase}
clicked={clicked}
setClicked={setClicked}
/>
<SectionList
sections={DATA}
keyExtractor={(item, index) => item + index}
renderItem={({ item }) => <Item title={item} />}
renderSectionHeader={({ section: { title } }) => (<Text style={styles.header}>{title}</Text>)}
/>
</View>
</View>
);
}
In the SectionList I have a name of the city and the phone number.
How can I make it so that when I type in the name of the city in the search bar, only the corresponding item is displayed?
SearchBar is already written and it's a simple TextInput that takes 4 arguments:
clicked - state of clicked or not
setClicked - function to change the state of clicked
searchPhrase - currrent text in the TextInput
setSearchPhrase - function to change the searchPhrase
You can filter the array you are using in the list based on the search input
sections={
DATA.filter((city)=>city.title.toUpperCase().includes(searchPhrase.toUpperCase()))
}
Related
I have a component that was working just fine until I started using the native-base library in React native. I'm being thrown the error element type invalid, saying that there's something wrong with the export but I can't see what the problem is
Here's the code
import {
StyleSheet,
View,
// Text,
FlatList,
} from "react-native";
import React, { useEffect, useState } from "react";
import {
Container,
Header,
Icon,
Item,
Input,
Text,
NativeBaseProvider,
Box,
} from "native-base";
// const data = require("");
import data from "../../assets/data/products.json";
import ProductList from "./ProductList";
const ProductContainer = () => {
const [products, setProducts] = useState([]);
const [productsFiltered, setProductsFiltered] = useState([]);
useEffect(() => {
setProducts(data);
setProductsFiltered(data);
return () => {
setProducts([]);
};
}, []);
return (
<NativeBaseProvider>
<Container>
<Header searchBar rounded>
<Item>
<Icon name="ios-search" />
<Input placeholder="Search" />
</Item>
<Icon name="ios-people" />
</Header>
<View style={styles.container}>
<View style={styles.listContainer}>
<FlatList
horizontal
data={products}
renderItem={({ item }) => (
<ProductList key={item.id} item={item} />
)}
keyExtractor={(item) => item.name}
/>
</View>
</View>
</Container>
</NativeBaseProvider>
);
};
export default ProductContainer;
const styles = StyleSheet.create({
container: {
},
listContainer: {
},
center: {
},
});
//I am rendering an API response with the help of FLatlist but when I press the expand option it will open all the accordions.................
import { View, Text, StyleSheet, FlatList } from 'react-native'
import React, { useState } from 'react'
import SearchBox from '../../components/SearchBox/SearchBox'
import { ListItem, Icon, Slider } from '#rneui/themed'
import { useSelector } from 'react-redux'
import { getAllPackages } from '../../feature/packageSlice'
const Rounds = () => {
const [expanded, setExpanded] = useState(false)
const pack = useSelector(getAllPackages)
//flatlist render item
const renderItem = ({ item }) => {
return (
<ListItem.Accordion
content={
<>
<ListItem.Content>
<ListItem.Title style={styles.header}>
{item.name}
</ListItem.Title>
</ListItem.Content>
</>
}
isExpanded={expanded}
onPress={() => {
setExpanded(!expanded)
}}
>
<View style={styles.card}>
<Text style={styles.font}>Water Supply Pressure</Text>
</View>
</View>
</ListItem.Accordion>
)
}
//main render
return (
<View>
<FlatList
data={pack}
renderItem={renderItem}
keyExtractor={(item) => item.id}
/>
</View>
</View>
)
}
export default Rounds
I want to open up the selected accordion only how can I achieve that, please help thanks...................................................................................................................................
If i understand your code correctly and this is one component (not fraction of few) your problem is following:
const [expanded, setExpanded] = useState(false)
This state variable is on top of your parent Component, so each rendered item points to it.
Therefore if you change it from any of your ListItem.Accordion, it will affect all of them.
BUT
If you change your renderItem to render Component. like this:
const renderItem = ({ item }) => {
return (
<AccordionListItem item={item}/>
)
}
Then you can move this state inside AccordionListItem itself, so it will create unique instance for each unique instance of component.
//imports
import React from ...
const AccordionListItem = ({item}) => {
const [expanded, setExpanded] = useState(false) <========= !
return (
<ListItem.Accordion
content={
<>
<ListItem.Content>
<ListItem.Title style={styles.header}>
{item.name}
</ListItem.Title>
</ListItem.Content>
</>
}
isExpanded={expanded}
onPress={() => {
setExpanded(!expanded)
}}
>
<View style={styles.card}>
<Text style={styles.font}>Water Supply Pressure</Text>
</View>
</View>
</ListItem.Accordion>
)
}
export default AccordionListItem ;
Here's the function-
const setLoading = (value) => {
const messages = dashboards.data.message.filter((item) => {
const title = item.dashboardTitle || item.dashboardName;
return title.toLowerCase().startsWith(value.toLowerCase());
});
setFiltered(messages);
console.log(filtered);
};
I want to display the variable 'messages' separately in my app, how would I do that? 'messages' variable needs to be displayed within the default react native 'Text' component. I have written down 'messages' below within Text component but currently it's not displaying anything (since it is within function) -
import React, { useState, useEffect, useReducer } from 'react';
import { View, Text, StyleSheet, FlatList, ActivityIndicator, Keyboard} from 'react-native';
import { Searchbar } from 'react-native-paper';
import { theme } from '../theme';
import MaterialIcons from 'react-native-vector-icons/MaterialIcons';
import { TouchableOpacity } from 'react-native-gesture-handler';
import { apiStateReducer } from '../reducers/ApiStateReducer';
import CognitensorEndpoints from '../services/network/CognitensorEndpoints';
import DefaultView from '../components/default/DefaultView';
import DashboardListCard from '../components/DashboardListCard';
const AppHeader = ({
scene,
previous,
navigation,
searchIconVisible = false,
}) => {
const [dashboards, dispatchDashboards] = useReducer(apiStateReducer, {
data: [],
isLoading: true,
isError: false,
});
const [filtered, setFiltered] = useState([]);
const setLoading = (value) => {
const messages = dashboards.data.message.filter((item) => {
const title = item.dashboardTitle || item.dashboardName;
return title.toLowerCase().startsWith(value.toLowerCase());
});
setFiltered(messages);
console.log(filtered);
};
const dropShadowStyle = styles.dropShadow;
const toggleSearchVisibility = () => {
navigation.navigate('Search');
};
useEffect(() => {
CognitensorEndpoints.getDashboardList({
dispatchReducer: dispatchDashboards,
});
}, []);
return (
<>
<View style={styles.header}>
<View style={styles.headerLeftIcon}>
<TouchableOpacity onPress={navigation.pop}>
{previous ? (
<MaterialIcons
name="chevron-left"
size={24}
style={styles.visible}
/>
) : (
<MaterialIcons
name="chevron-left"
size={24}
style={styles.invisible}
/>
)}
</TouchableOpacity>
</View>
<Text style={styles.headerText}>
{messages}
</Text>
<View style={styles.headerRightIconContainer}>
{searchIconVisible ? (
<TouchableOpacity
style={[styles.headerRightIcon, dropShadowStyle]}
onPress={toggleSearchVisibility}>
<MaterialIcons name="search" size={24} style={styles.visible} />
</TouchableOpacity>
) : (
<View style={styles.invisible} />
)}
</View>
</View>
</>
);
};
If your messages variable is an array you can map it
{messages.map((message, key)=>(
<Text style={styles.headerText}>
{message.dashboardName}
</Text>
))}
Since your messages variable is stored in 'filtered' state, you can map it by doing this:
{filtered.map((item, index) => <Text key={index}>{item.dashboardName}<Text>)}
I'm buiding an application that receives foreign exchange currency pairs e.g EURUSD with their respective prices e.g EURUSD AskPrice: 0.90345 BidPrice: 0.90365 . The user of the application is supposed to set the price in a textInput at which they would like to be alerted once that price is reached. I have tried creating a function for this but it logs the input price immediately instead of checking the condition first and then waiting for the condition to be met first before logging. Below is the Code:
//Datafetching
import React, {createContext, useState, useEffect}from 'react'
import {ActivityIndicator} from 'react-native'
import axios from '../utils/axios'
const CurrencyContext = createContext();
const CurrencyProvider =(props) => {
const [data, setData] = useState([])
const [isLoading, setIsloading] = useState(true)
useEffect(() => {
const interval = setInterval(() => {
const fetchpairs = async() => {
const results = await axios.get('/v3/accounts/101-004-14328428-002/pricing?instruments=AUD_CAD%2CAUD_CHF%2CAUD_JPY%2CAUD_NZD%2CAUD_USD%2CCAD_CHF%2CCAD_JPY%2CCHF_JPY%2CEUR_AUD%2CEUR_CAD%2CEUR_CHF%2CEUR_GBP%2CEUR_NOK%2CEUR_NZD%2CEUR_USD%2CGBP_AUD%2CGBP_CAD%2CGBP_CHF%2CGBP_USD%2CGBP_JPY%2CNZD_CAD%2CNZD_CHF%2CNZD_JPY%2CUSD_CAD%2CUSD_JPY%2CUSD_CHF%2CUSD_ZAR%2CUSD_MXN')
setData(results.data)
setIsloading(false)
}
fetchpairs()
},1000)
}, []);
if(isLoading) {
return (
<ActivityIndicator size="large"/>
)
}else
return (
<CurrencyContext.Provider
value={{
data,
setData,
isLoading,
setIsloading
}}>
{props.children}
</CurrencyContext.Provider>
)
}
export {CurrencyProvider, CurrencyContext}
//HomeScreen
import React, {useContext, useState, useEffect} from 'react'
import { Text, View, ScrollView, TouchableOpacity, Modal, TextInput, ToastAndroid, Picker, Alert } from 'react-native'
import {ListItem, Card, Button, Icon} from 'react-native-elements'
import {ActionSheet} from 'native-base'
//import CurrencyPair from '../../CurrencyPair'
import {firebase} from '../../../firebase/config'
import {CurrencyContext} from '../../../context/Context'
import styles from '../HomeScreen/styles'
function HomeScreen({navigation, props}) {
const currency = useContext(CurrencyContext);
//hook for the modal
const [modalopen, setModalOpen] = useState(false)
//hook for the clicked currency pair
const [clickedindex, setClickedIndex] = useState(0)
//hook for the actionsheet
const[sheet, setSheet] = useState(null)
//Hooks for the alert
const [pricealert, setPricealert] = useState('')
//function for checking alert condition
const checkAlertCondition = (pricealert) => {
if(pricealert >= {...currency.data.prices[clickedindex].closeoutAsk} ){
setPricealert(pricealert)
console.log("Price" + pricealert + "has been hit")
}
else if(pricealert <= {...currency.data.prices[clickedindex].closeoutAsk})
{
setPricealert(pricealert)
console.log("Price" + pricealert + "has been hit")
}
else
{
console.log("Set your alert price")
}
}
//toast method that will be called when the ok button is called
const showToastWithGravityAndOffset = () => {
ToastAndroid.showWithGravityAndOffset(
"Alert created successfully",
ToastAndroid.SHORT,
ToastAndroid.BOTTOM,
25,
50
);
};
const BUTTONS = [
{ text: "SMS", icon: "chatboxes", iconColor: "#2c8ef4" },
{ text: "Email", icon: "analytics", iconColor: "#f42ced" },
{ text: "Push Notification", icon: "aperture", iconColor: "#ea943b" },
{ text: "Delete", icon: "trash", iconColor: "#fa213b" },
{ text: "Cancel", icon: "close", iconColor: "#25de5b" }
];
const DESTRUCTIVE_INDEX = DESTRUCTIVE_INDEX;
const CANCEL_INDEX = CANCEL_INDEX;
return (
<ScrollView>
<Modal
visible={modalopen}
animationType={"fade"}
>
<View style={styles.modal}>
<View>
<Text style={{textAlign: "center", fontWeight: "bold"}}>
{currency.data.prices[clickedindex].instrument}
</Text>
<Text style={{textAlign: "center"}}>
{currency.data.prices[clickedindex].closeoutAsk}/{currency.data.prices[clickedindex].closeoutBid}
</Text>
<Card.Divider/>
<View style={{ flexDirection: "row"}}>
<View style={styles.inputWrap}>
<TextInput
style={styles.textInputStyle}
value={pricealert}
onChangeText = {(pricealert) => setPricealert(pricealert)}
placeholder="Alert Price"
placeholderTextColor="#60605e"
numeric
keyboardType='decimal-pad'
/>
</View>
<View style={styles.inputWrap}>
</View>
</View>
<TouchableOpacity
onPress={() =>
ActionSheet.show(
{
options: BUTTONS,
cancelButtonIndex: CANCEL_INDEX,
destructiveButtonIndex: DESTRUCTIVE_INDEX,
title: "How do you want to receive your notification"
},
buttonIndex => {
setSheet({ clicked: BUTTONS[buttonIndex] });
}
)}
style={styles.button}
>
<Text>ActionSheet</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.button}
onPress={() => {setModalOpen(false); checkAlertCondition(pricealert);showToastWithGravityAndOffset();} }>
<Text style={styles.buttonTitle}>OK</Text>
</TouchableOpacity>
</View>
</View>
</Modal>
<Card>
<Text style={{textAlign: "center"}}>
Welcome
</Text>
<Button title="Sign Out" type="outline" onPress ={() => firebase.auth().signOut()}/>
<Button title="My Alerts" onPress ={() =>navigation.navigate("AlertScreen") }/>
</Card>
<View>
{currency.data.prices && currency.data.prices.map((prices, index) => {
return (
<ListItem
key={index}
onPress = {() => {setModalOpen(true);setClickedIndex(index);}}
bottomDivider>
<ListItem.Content>
<ListItem.Title>
{currency.data.prices[index].instrument} {currency.data.prices[index].closeoutAsk} {currency.data.prices[index].closeoutBid}
</ListItem.Title>
</ListItem.Content>
</ListItem>
)
})
}
</View>
</ScrollView>
)
}
export default HomeScreen
inside onPress you are calling checkAlertCondition but with no params yet inside that function you are expecting the pricealert also you are trying to use >= with the left hand side being an object.
Try this:
const checkAlertCondition = (pricealert) => {
if(currency.data.prices[clickedindex].AskPrice >= pricealert){
setPricealert(pricealert)
console.log("Price" + pricealert + "has been hit")
}
}
I just started to learn React-native. In this app I have a two buttons in header, first 'Todo', second 'Tags'. I want to chang content by press on these buttons. I think I need to change state.for clarityWhat I mean, when i tap on the button Tags, below I get TagScreen component, exactly the same for the button Todo. How to connect these components so that they work correctly?
app.js
import React, { useState } from 'react'
import { StyleSheet, View, FlatList } from 'react-native'
import { Navbar } from './src/Navbar'
import { TagScreen } from './src/screens/TagScreen'
import { TodoScreen } from './src/screens/TodoScreen'
export default function App() {
const [todos, setTodos] = useState([])
const [tags, setTags] = useState([])
const [appId, setAppId] = useState([])
const addTodo = title => {
setTodos(prev => [
...prev,
{
id: Date.now().toString(),
title
}
])
}
const addTags = title => {
setTags(prev => [
...prev,
{
id: Date.now().toString(),
title
}
])
}
const removeTags = id => {
setTags(prev => prev.filter(tag => tag.id !== id))
}
const removeTodo = id => {
setTodos(prev => prev.filter(todo => todo.id !== id))
}
return (
<View>
<Navbar title='Todo App!' />
<View style={styles.container}>
<TagScreen addTags={addTags} tags={tags} removeTags={removeTags}/>
{/* <TodoScreen todos={todos} addTodo={addTodo} removeTodo={removeTodo} /> */}
{/* HERE MUST CHANGED COMPONENTS */}
</View>
</View>
)
}
const styles = StyleSheet.create({
container: {
paddingHorizontal: 30,
paddingVertical: 20
}
})
navbar.js
import React from 'react'
import { View, Text, StyleSheet, Button, TouchableOpacity } from 'react-native'
export const Navbar = ({ title }) => {
return (
<View style={styles.padding}>
<View style={styles.navbar}>
<TouchableOpacity
style={styles.button}
>
<Text>Todo</Text>
</TouchableOpacity>
<TouchableOpacity
style={styles.button}
>
<Text>Tags</Text>
</TouchableOpacity>
<Text style={styles.text}>{title}</Text>
</View>
</View>
)
}
well you need to track the visiblity of what is visible in your state,
in your App component, do this;
const [showTodos, setShowTodos] = useState(false);
const makeTodosInvisible= () => setShowTodos(false);
const makeTodosVisible = () => setShowTodos(true);
return (
<View>
<Navbar onTodoPress={makeTodosVisible } onTagPress={makeTodosInvisible} title='Todo App!' />
<View style={styles.container}>
{showTodos
? <TodoScreen todos={todos} addTodo={addTodo} removeTodo={removeTodo} />
: <TagScreen addTags={addTags} tags={tags} removeTags={removeTags}/>
}
{/* <TodoScreen todos={todos} addTodo={addTodo} removeTodo={removeTodo} /> */}
{/* HERE MUST CHANGED COMPONENTS */}
</View>
</View>
)
and in your navbar.js do this
export const Navbar = ({ title, onTodoPress, onTagPress}) => {
return (
<View style={styles.padding}>
<View style={styles.navbar}>
<TouchableOpacity
style={styles.button}
onPreesed={onTodoPress} // will hide Tags and show Todos
>
<Text>Todo</Text>
</TouchableOpacity>
<TouchableOpacity
style={styles.button}
onPreesed={onTagPress} // will show Tags and hide Todos
>
<Text>Tags</Text>
</TouchableOpacity>
<Text style={styles.text}>{title}</Text>
</View>
</View>
)
}