React Native Remove Item and button - reactjs

I want when I click button inside access file remove the same item in months array inside Home file.
How can I solve this?
App.js
this file conncet screen.
import {StyleSheet, View} from 'react-native';
import {createStackNavigator} from '#react-navigation/stack';
import Home from './src/components/Home';
import {NavigationContainer} from '#react-navigation/native';
import Access from './src/components/access';
const Stack = createStackNavigator();
const App = () => {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Home" component={Home} />
<Stack.Screen name="access" component={Access} />
</Stack.Navigator>
</NavigationContainer>
);
};
export default App;
ButtonCicle.js
this file make circle.
import { View, Text,TouchableOpacity } from 'react-native';
import styles from './Styles/ButtonCircleStyles';
export default function ButtonCicle({BtnName, onPress}) {
return (
<TouchableOpacity style={styles.buttonContainer} onPress={onPress}>
<Text style={styles.button}>{BtnName}</Text>
</TouchableOpacity>
);
}
ButtonCircleStyles.js
this file make style
import {StyleSheet, Dimensions} from 'react-native';
const height = Dimensions.get('window').height;
const width = Dimensions.get('window').width;
const styles = StyleSheet.create({
buttonContainer:
{
backgroundColor: 'red',
borderRadius: 50,
width: width / 5,
height: width / 5,
justifyContent: 'center',
marginStart: '4%',
marginBottom: '4%',
},
button:
{
fontSize: 25,
textAlign: 'center',
},
});
export default styles;
Home.js
this file make array and onPress to another screen
import React from 'react';
import {StyleSheet, View} from 'react-native';
import ButtonCicle from './ButtonCircle';
const Home = ({navigation}) => {
const months = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
const listbutton = months.map((i, key) => (
<ButtonCicle
BtnName={i}
key={key}
onPress={() => navigation.navigate('access') || alert(i)}
/>
));
return (
<>
<View style={styles.container}>{listbutton}</View>
</>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#ecf0f1',
padding: 8,
marginTop: '10%',
flexDirection: 'row',
height: 300,
flexWrap: 'wrap',
},
});
export default Home;
access.js
import React from 'react'
import { View, Text, Button } from 'react-native'
export default function access({navigation}) {
return (
<View>
<Text>Home</Text>
<Button title='Click' onPress={() => navigation.navigate('Home')} />
</View>
)
}
I want when I click button inside access file remove the same item in months array inside Home file.
How can I solve this?
How create it ?

You can try with a callback. Define a function inside Home.js that remove the element from the array. Then you could pass this callback as a route param
navigation.navigate('access', {deleteItem: //your callback})
And in the access.js file you get this callback
const deleteItem = navigation.getParam('deleteItem');
And call it before navigate back to home
const onPress = () => {
deleteItem();
navigation.navigate('Home');
}
<Button title='Click' onPress={onPress} />

Related

navigation.navigate is not a function. (In 'navigation.navigate("HomeScreen")', 'navigation.navigate' is undefined)

I m very new in react native and I m getting this error. Please help!
navigation.navigate is not a function. (In 'navigation.navigate("HomeScreen")', 'navigation.navigate' is undefined)
import { View, Text,Button,StyleSheet, TouchableOpacity } from 'react-native'
import React, {useState} from 'react'
import { NavigationContainer,CommonActions, useNavigation } from '#react-navigation/native';
const GetOtpButton = (navigation) => {
return (
<View >
<TouchableOpacity style = {styles.button} onPress={() => navigation.navigate("HomeScreen") } >
<Text style = {styles.text}>Log in</Text>
</TouchableOpacity>
</View>
)
}
const styles = StyleSheet.create({
button: {
justifyContent: 'center',
alignItems: 'center',
backgroundColor: "white",
width: "100%",
height: 50,
borderColor: "#E13C72",
backgroundColor: "#E13C72",
borderWidth: 0.1,
borderRadius: 80,
// marginBottom: 40,
// marginVertical: 5,
// marginTop: 10,
},
text: {
justifyContent: 'center',
textAlign: 'center',
color: "white",
fontWeight: 'bold'
}
});
export default GetOtpButton
---------------------App.js------------------
import react from "react";
import { StatusBar } from "expo-status-bar";
import { SafeAreaView, StyleSheet, Text, View, Dimensions } from "react-native";
import SigninScreen from "./src/SigninScreen/SigninScreen";
import HomeScreen from "./src/HomeScreen/HomeScreen";
import { NavigationContainer, StackActions } from '#react-navigation/native';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
const Stack = createNativeStackNavigator();
export default function App() {
return (
<NavigationContainer>
<Stack.Navigator initialRouteName="SigninScreen" options={{headerShown: false}}>
<Stack.Screen name = 'SigninScreen' component={SigninScreen} options={{headerShown: false}}/>
<Stack.Screen name = 'HomeScreen' component={HomeScreen} options={{headerShown: false}}/>
</Stack.Navigator>
</NavigationContainer>
);
}
const styles = StyleSheet.create({
root: {},
container: {
flex: 1,
flexDirection: "row",
alignItems: "center",
justifyContent: "center",
backgroundColor: "#FFFFFF",
},
});
The component GetOptButton is not defined as a screen in the navigator, thus the navigation object will not be passed to it automatically by the navigation framework. Thus, you have multiple choices here.
Define it as a screen inside the navigator
<Stack.Screen name = 'GetOpt' component={GetOptButton} />
The framework will now pass the navigation object to the GetOptButton component. You can access it as follows.
const GetOtpButton = ({navigation}) => { ... }
Now, since GetOptButton seems to be a component rather than a screen to which you will navigate, it might not make much sense to define it inside the navigator.
Pass the navigation object from a screen which is defined in the navigator that uses the GetOptButton component
// this works, since `Homescreen` is defined as a screen in your navigator
const HomeScreen = ({navigation}) => {
return (
<GetOptButton navigation={navigation} />
)
}
Destructure the navigation object inside GetOptButton as shown above.
Use the useNavigation hook
For some components it might not make sense to pass the navigation object from its parent, e.g. if the component is deeply nested. For this cases you can use the useNavigation hook.
const GetOptButton = () => {
const navigation = useNavigation()
}
You are not showing how GetOtpButton is used but guessing that navigation is passed as prop to GetOtpButton you need to get to navigation like this
const GetOtpButton = ({navigation}) => {
return (
<View >
<TouchableOpacity style = {styles.button} onPress={() => navigation.navigate("HomeScreen") } >
<Text style = {styles.text}>Log in</Text>
</TouchableOpacity>
</View>
)
}
See that the difference is that navigation is surrounded by curly brackets, so later you get the parameter navigation inside the props

NativeBase showing error while using in Jest testing

I want to test a basic component name TitleHeader which uses HStack and VStack from native base.
The component:-
import {Center, HStack, VStack} from 'native-base';
import React from 'react';
import {View, Text} from 'react-native';
import appColors from '../../constants/appColors';
//Icon Imports
import Ionicons from 'react-native-vector-icons/Ionicons';
import {TouchableOpacity} from 'react-native-gesture-handler';
import {useNavigation} from '#react-navigation/core';
const TitleHeader = ({
title = 'Header Title',
navigationBack = false,
center = false,
onBackPress,
drawer = false,
style = {},
}) => {
console.log(title);
const navigation = useNavigation();
const handleGoBack = () => {
if (onBackPress && typeof onBackPress === 'function') {
onBackPress();
} else if (drawer) {
navigation.goBack();
} else {
navigation.pop();
}
};
return (
<HStack
bg={appColors.primaryBlue}
style={[
{
height: 55,
position: 'relative',
},
style,
]}
alignItems="center"
px={3}>
{navigationBack ? (
<View style={{position: 'absolute', zIndex: 10, left: 10}}>
<TouchableOpacity
onPress={handleGoBack}
style={{
width: 35,
height: 35,
justifyContent: 'center',
alignItems: 'center',
}}>
<Ionicons name="arrow-back" size={26} color="white" />
</TouchableOpacity>
</View>
) : null}
<VStack flex={1} alignItems="center" pl={2}>
<Text
color="white"
fontSize="lg"
numberOfLines={1}
ellipsizeMode="tail"
style={
center
? {}
: {
width: '80%',
}
}>
{title}
</Text>
</VStack>
</HStack>
);
};
export default TitleHeader;
Following is my test case which uses jest for testing:-
import React from 'react';
import {render} from '#testing-library/react-native';
import TitleHeader from '../src/components/AppHeaders/TitleHeader';
import renderer from 'react-test-renderer';
import {NavigationContainer} from '#react-navigation/native';
import {NativeBaseProvider} from 'native-base';
jest.mock('native-base');
const wrapper = ({children}) => (
<NativeBaseProvider
initialWindowMetrics={{
frame: {x: 0, y: 0, width: 0, height: 0},
insets: {top: 0, left: 0, right: 0, bottom: 0},
}}>
{children}
</NativeBaseProvider>
);
describe('Testing Title Header for screens', () => {
test('should render title header', () => {
const tree = renderer
.create(
<NavigationContainer>
<TitleHeader title={'HEADER TEST'} />
</NavigationContainer>,
{wrapper},
)
.toJSON();
expect(tree).toMatchSnapshot();
});
});
But I am getting this error inspite of using jest.mock('native-base') in my jest.setup.js.
I am new to testing please help me render this component first and test it using jest. Also, one more thing to add is that if I do not use the wrapper function it throws error telling me that "theme is not defined. Did you forget to wrap your app inside NativeBaseProvider?".
If the component that you trying to test has the theme coming from NativeBase you need to provide the <ThemeProvider/> (Spelling might differ depending on the library, in your case <NativeBaseProvider/>
If you do jest.mock('native-base') and you do not return anything will cause Nothing was returned from render error.
Did you add native-base library to transformIgnorePatterns of jest.config as suggested in this issue?

Too much space between the appbar and status bar

I am making an app, where I want to use react navigation.
For some reason, whenever I use drawers in react navigation, there is a huge space between the status bar and the drawer app bar.
Here is my code for the ho -
import { StatusBar } from "expo-status-bar";
import * as React from "react";
import { useState, useEffect } from "react";
import { StyleSheet, Text, View, ScrollView } from "react-native";
import Constants from "expo-constants";
import Header from "../Header";
import { Flexbox } from "../Layout";
import Card from "../Card";
import { marginAboveCard } from "../../constants/constants";
import Row from "../Row";
import { convertToIndianNumberingFormat } from "../../utils/utils";
const HomeScreen = ({ navigation }) => {
const [cardsData, setCardsData] = useState({
confirmed: 0,
active: 0,
recovered: 0,
deceased: 0,
tests: 0,
critical: 0,
});
const [lastUpdated, setLastUpdated] = useState("");
useEffect(() => {
const getData = async () => {
const cardsDataResponse = await fetch(
"https://disease.sh/v3/covid-19/all"
);
const cardsDataFetched = await cardsDataResponse.json();
setCardsData({
confirmed: convertToIndianNumberingFormat(
cardsDataFetched.cases
),
active: convertToIndianNumberingFormat(cardsDataFetched.active),
recovered: convertToIndianNumberingFormat(
cardsDataFetched.recovered
),
deceased: convertToIndianNumberingFormat(
cardsDataFetched.deaths
),
tests: convertToIndianNumberingFormat(cardsDataFetched.tests),
critical: convertToIndianNumberingFormat(
cardsDataFetched.critical
),
});
const time = new Date(cardsDataFetched.updated);
const lastupdated = time.toLocaleTimeString();
setLastUpdated(`Last updated at ${lastupdated}`);
};
getData();
}, []);
return (
<ScrollView style={styles.main}>
<View style={{ marginTop: Constants.statusBarHeight }}>
<StatusBar style="auto" />
<Header text="COVID-19" />
<Text style={styles.lastUpdatedText}>{lastUpdated}</Text>
<View style={{ marginTop: marginAboveCard }}>
<Flexbox style={{ marginTop: 15 }}>
<Card
background="red"
title="Confirmed"
number={cardsData.confirmed}
/>
<Card
background="#3877F0"
title="Active"
number={cardsData.active}
/>
</Flexbox>
<Flexbox style={{ marginTop: marginAboveCard }}>
<Card
background="#47CC3C"
title="Recovered"
number={cardsData.recovered}
/>
<Card
background="#868686"
title="Deceased"
number={cardsData.deceased}
/>
</Flexbox>
<Flexbox style={{ marginTop: marginAboveCard }}>
<Card
background="#E85FEB"
title="Tests"
number={cardsData.tests}
/>
<Card
background="#5BF8B6"
title="Critical"
number={cardsData.critical}
/>
</Flexbox>
</View>
<View style={{ marginTop: 30 }}>
<Header text="TABLE STATISTICS" />
</View>
</View>
</ScrollView>
);
};
export default HomeScreen;
const styles = StyleSheet.create({
main: {
flex: 1,
backgroundColor: "#000232",
},
lastUpdatedText: {
color: "white",
textAlign: "center",
marginTop: 12,
fontSize: 15,
},
});
My app.jsx -
import * as React from "react";
import HomeScreen from "./components/screens/HomeScreen";
import VaccineScreen from "./components/screens/VaccineScreen";
import { NavigationContainer } from "#react-navigation/native";
import { createDrawerNavigator } from "#react-navigation/drawer";
const Drawer = createDrawerNavigator();
export default function App() {
return (
<NavigationContainer>
<Drawer.Navigator initialRouteName="Home">
<Drawer.Screen name="Home" component={HomeScreen} />
<Drawer.Screen name="Vaccine" component={VaccineScreen} />
</Drawer.Navigator>
</NavigationContainer>
);
}
If you look at the code of home screen properly, you would see a status style component which is set to auto. Even after removing it, the space is there. There are no errors in the console of any sort. This error started coming when I used react navigation drawer. Is there a way I can remove the space?
Did you try to move StatusBar as top most child like my sample below?
....
<View>
<StatusBar style="auto" />
<ScrollView style={styles.main}>
<View style={{ marginTop: Constants.statusBarHeight }}>
...
How you define the header title and the drawer icon?

making a virtualized list with a separate file in react

I created a to do list app in app.js and a virtualized list in VirtualizedList.js but none of the virtualized list code is displaying although I imported it into app.js properly.
Here is the VirtualizedList.js code.
import React from 'react';
import { SafeAreaView, View, VirtualizedList, StyleSheet, Text,
StatusBar } from 'react-native';
const DATA = [];
const getItem = (data, index) => ({
id: Math.random().toString(12).substring(0),
title: `Item ${index+1}`
});
const getItemCount = (data) => 50;
const Item = ({ title }) => (
<View style={styles.item}>
<Text style={styles.title}>{title}</Text>
</View>
);
const App = () => {
return (
<SafeAreaView style={styles.container}>
<VirtualizedList
data={DATA}
initialNumToRender={4}
renderItem={({ item }) => <Item title={item.title} />}
keyExtractor={item => item.key}
getItemCount={getItemCount}
getItem={getItem}
/>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
marginTop: StatusBar.currentHeight,
},
item: {
backgroundColor: '#f9c2ff',
height: 100,
justifyContent: 'center',
marginVertical: 7,
marginHorizontal: 24,
padding: 20,
},
title: {
fontSize: 25,
},
});
export default App;
This is how I imported VirtualizedList into app.js:
import VirtualizedList from '/Users/myname/Applications/todo-
app/src/components/VirtualizedList';
Normally you would export default your list in VirtualizedList.js and you would import them in your App.js (renderer) as a normal object. But I would have to see the code to be sure

How do I create stack navigation tabs for a separate .tsx file in react js

At the start of my application, there is two tabs at the bottom of the screen (these tabs came in the template I downloaded from Expo for react js). I made a new screen, called homepage, and I want to now replicate those same tabs at the bottom, but I can't figure out how. I tried using a stack navigator but it did not work.
I want it to look like this
Here is my code for homescreen
import * as React from 'react';
import { StyleSheet, Button, TextInput } from 'react-native';
import EditScreenInfo from '../components/EditScreenInfo';
import { Text, View } from '../components/Themed';
import { NavigationContainer } from '#react-navigation/native';
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
import FAQ_Screen from './FAQ_Screen';
import NewsScreen from './NewsScreen';
import { createStackNavigator } from '#react-navigation/stack';
import BottomTabNavigator from '../navigation/BottomTabNavigator';
import NotFoundScreen from './NotFoundScreen';
const Stack = createStackNavigator();
export default function HomeScreen() {
return (
<View style={styles.container}>
<Text> Home </Text>
<select>
<option> Station 1 </option>
<option> Staton 2 </option>
</select>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
title: {
fontSize: 20,
fontWeight: 'bold',
},
separator: {
marginVertical: 30,
height: 1,
width: '80%',
},
});
You should declare tabs inside Tab.Navigator.
These screens can be separate .tsx or js files. I did using js, to be able to show using Expo. However, ts/js doesn't change the behavior.
I did a working example:
https://snack.expo.io/#mayconjcm/tab-navigation-%7C-react-navigation
You can also see the code here:
Home:
import * as React from 'react';
import { Text, View } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
import HomeTab from './Tab1';
import SettingsTab from './Tab2';
const Tab = createBottomTabNavigator();
function MyTabs() {
return (
<Tab.Navigator>
<Tab.Screen name="Home" component={HomeTab} />
<Tab.Screen name="Settings" component={SettingsTab} />
</Tab.Navigator>
);
}
export default function App() {
return (
<NavigationContainer>
<MyTabs />
</NavigationContainer>
);
}
Tab1:
import * as React from 'react';
import { Text, View } from 'react-native';
const HomeTab = () => {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Home!</Text>
</View>
);
}
export default HomeTab;
Tab2:
import * as React from 'react';
import { Text, View } from 'react-native';
const SettingsTab = () => {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Settings!</Text>
</View>
);
}
export default SettingsTab;

Resources