usecontext without child component? - reactjs

I'm wanting to pass a state from my WeatherComponent through to my UserForm component and ideally would like to do this without making the UserForm a child component. At the moment I have the UserForm as a child component and that component is working fine when I render it because it's getting the weather state from the WeatherComponent. But now when I want to render my WeatherComponent it renders the UserComponent as well.
Is there another way I could use useContext or a method that doesn't rely on making a child component?
WeatherComponent:
import axios from 'axios';
import { useEffect, useState, createContext } from 'react';
import { Weather } from '../types';
import { MdWbSunny } from 'react-icons/md';
import { IoIosPartlySunny } from 'react-icons/io';
import { BsFillCloudSnowFill } from 'react-icons/bs';
import { Title, Text, Container } from '#mantine/core';
import UserForm from './UserForm';
export const WeatherContext = createContext<any>(null);
const WeatherComponent = () => {
const [weather, setWeather] = useState<Weather | null>();
const fetchWeatherData = async () => {
const response = await axios.get('http://mock-api-call/weather/get-weather');
setWeather(response.data.result.weather);
};
useEffect(() => {
fetchWeatherData();
}, []);
return (
<Container>
<WeatherContext.Provider value={weather?.forcast}>
<UserForm />
</WeatherContext.Provider>
<Title order={2}>
{weather?.forcast === 'Sunny' ? (
<MdWbSunny data-testid="sunny" />
) : weather?.forcast === 'Snowing' ? (
<BsFillCloudSnowFill data-testid="snowing" />
) : (
<IoIosPartlySunny data-testid="overcast" />
)}
</Title>
<Text size="xl" data-testid="forcast">
{weather?.forcast}
</Text>
<Text size="lg" data-testid="temp">
Temp: {`${weather?.min} to ${weather?.max}`}
</Text>
<Text size="md" data-testid="description">
{weather?.description}
</Text>
</Container>
);
};
export default WeatherComponent;
UserForm:
import React, { useContext, useState } from 'react';
import { Container, Title, TextInput, Button, Group, Header } from '#mantine/core';
import { useStateWithLocalStorage } from './UseStateWithLocalStorage';
import { WeatherContext } from './WeatherComponent';
import { MdWbSunny } from 'react-icons/md';
import { BsFillCloudSnowFill } from 'react-icons/bs';
import { IoIosPartlySunny } from 'react-icons/io';
const UserForm = () => {
const [inputValue, setInputValue] = useStateWithLocalStorage('', 'form');
const [show, setShow] = useState(true);
const weatherIcon = useContext(WeatherContext);
function handleChange(event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) {
setInputValue(() => ({
[event.target.name]: event.target.value,
}));
}
return (
<Header height={56} mb={120}>
<Container
style={{
display: 'flex',
flexDirection: 'row',
backgroundColor: 'gray',
justifyContent: 'space-between',
color: 'white',
alignItems: 'center',
padding: '10px',
fontSize: '25px',
fontWeight: 'bold',
boxShadow: '0 3px 6px 0 #555',
}}
>
<Group>
<Title order={2}>Welcome </Title>
{show && (
<TextInput
type="text"
name="name"
id="name"
placeholder="enter your name"
onChange={handleChange}
value={inputValue.name}
/>
)}
{show && <Button onClick={() => setShow((prev) => !prev)}>SAVE</Button>}
<Title order={2}>{inputValue.name ? inputValue.name : ''}</Title>
</Group>
<Group style={{ display: 'flex', justifyContent: 'flex-end' }}>
<Title order={2}>
{weatherIcon === 'Sunny' ? (
<MdWbSunny data-testid="sunny" />
) : weatherIcon === 'Snowing' ? (
<BsFillCloudSnowFill data-testid="snowing" />
) : (
<IoIosPartlySunny data-testid="overcast" />
)}
</Title>
</Group>
</Container>
</Header>
);
};
export default UserForm;

Related

The action 'NAVIGATE' with payload was not handled by any navigator [React Native]

Hello I have 3 drawer Navigators[Home,List,Contact] and I want to navigate from List Screen to an other Screen called EditScreen this Why I create a Stack Navigator on the List Screen But I got an error when I press the name on the table thet should take me to From the List Screen to The Edit Screen.
App.js
import * as React from 'react';
import { NavigationContainer } from '#react-navigation/native';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
import { createDrawerNavigator } from '#react-navigation/drawer';
import COLORS from './src/conts/colors';
import HomeScreen from './Screens/HomeScreen';
import ListScreen from './Screens/ListScreen';
import FormScreen from './Screens/FormScreen';
import EditScreen from './Screens/EditScreen';
const Stack = createNativeStackNavigator();
const Drawer = createDrawerNavigator();
const App = () => {
return (
<NavigationContainer>
<Drawer.Navigator initialRouteName="Home" screenOptions={{
headerStyle: {
backgroundColor: COLORS.lightkBlue
},
headerTintColor: '#fff',
headerTitleStyle: {
fontWeight: 'bold'
}
}}>
<Drawer.Screen name="Home" component={HomeScreen} />
<Drawer.Screen name="List" component={ListScreen} />
<Drawer.Screen name="Form" component={FormScreen} />
</Drawer.Navigator>
</NavigationContainer>
);
}
export default App;
ListScreen.js
import React, { useState } from 'react';
import { StyleSheet, SafeAreaView, ScrollView,Text, View, Modal } from 'react-native';
import { DataTable } from 'react-native-paper';
import { NavigationContainer } from '#react-navigation/native';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
import COLORS from '../src/conts/colors';
import Button from '../src/views/components/Button';
import EditScreen from './EditScreen';
const Stack = createNativeStackNavigator();
function Edit() {
return (
<Stack.Navigator>
<Stack.Screen name="Edit" component={EditScreen} />
</Stack.Navigator>
);
}
const List = ({navigation}) => {
const data = [
{id:1,name:"Hassane1",phone:"068888188888",email:"contact#gemail.com"},
{id:2,name:"Hassane2",phone:"068888888288",email:"contact#gemail.com"},
{id:3,name:"Hassane3",phone:"068888388888",email:"contact#gemail.com"},
]
const renderList = data.map((item)=>{
return(
<DataTable.Row key={item.id}>
<DataTable.Cell onPress={() => navigation.navigate("Edit",{item})} >{item.name}</DataTable.Cell>
<DataTable.Cell>{item.email}</DataTable.Cell>
<DataTable.Cell>{item.phone}</DataTable.Cell>
</DataTable.Row>
)
})
return (
<SafeAreaView style={{backgroundColor: COLORS.white, flex: 1}}>
<ScrollView
contentContainerStyle={{paddingTop: 50, paddingHorizontal: 20}}>
<Text style={{color: COLORS.black, fontSize: 40, fontWeight: 'bold'}}>
List of Companies
</Text>
<Text style={{color: COLORS.grey, fontSize: 18, marginVertical: 10}}>
Check Our Companies Details
</Text>
<DataTable style={styles.container} >
<DataTable.Header style={styles.tableHeader} >
<DataTable.Title>Name</DataTable.Title>
<DataTable.Title>email</DataTable.Title>
<DataTable.Title>Phone</DataTable.Title>
</DataTable.Header>
</DataTable>
{renderList}
</ScrollView>
</SafeAreaView>
);
};
export default List;
const styles = StyleSheet.create({
container: {
padding: 15,
},
tableHeader: {
backgroundColor: '#F3F4FB',
},
modalButtonView: {
}
});
EditScreen.js
import React, { useState } from 'react';
import {
View,
Text,
TextInput,
SafeAreaView,
Keyboard,
ScrollView,
Alert,
} from 'react-native';
import COLORS from '../src/conts/colors';
import Button from '../src/views/components/Button';
import Input from '../src/views/components/Input';
import Loader from '../src/views/components/Loader';
const EditScreen = (props) => {
const {id,name,phone,email} = props.route.params.item
const [inputs, setInputs] = React.useState({
name: '',
email: '',
phone: '',
});
const [errors, setErrors] = React.useState({});
const [loading, setLoading] = React.useState(false);
const validate = () => {
Keyboard.dismiss();
let isValid = true;
if (!inputs.name) {
handleError('Please input Company', 'name');
isValid = false;
}
if (!inputs.email) {
handleError('Please input email', 'email');
isValid = false;
} else if (!inputs.email.match(/\S+#\S+\.\S+/)) {
handleError('Please input a valid email', 'email');
isValid = false;
}
if (!inputs.phone) {
handleError('Please input phone number', 'phone');
isValid = false;
}
{/*if (isValid) {
register();
}*/}
};
const handleOnchange = (text, input) => {
setInputs(prevState => ({...prevState, [input]: text}));
};
const handleError = (error, input) => {
setErrors(prevState => ({...prevState, [input]: error}));
};
return (
<SafeAreaView style={{backgroundColor: COLORS.white, flex: 1}}>
<Loader visible={loading} />
<ScrollView
contentContainerStyle={{paddingTop: 50, paddingHorizontal: 20}}>
<Text style={{color: COLORS.black, fontSize: 40, fontWeight: 'bold'}}>
Edit
</Text>
<Text style={{color: COLORS.grey, fontSize: 18, marginVertical: 10}}>
Now You Can Edit !
</Text>
<View style={{marginVertical: 20}}>
<Input
onChangeText={text => handleOnchange(text, 'name')}
onFocus={() => handleError(null, 'name')}
iconName="account-outline"
label="Company"
placeholder="Enter your Company Name"
error={errors.name}
defaultValue={name}
/>
<Input
onChangeText={text => handleOnchange(text, 'email')}
onFocus={() => handleError(null, 'email')}
iconName="email-outline"
label="Email"
placeholder="Enter your email address"
error={errors.email}
defaultValue={email}
/>
<Input
keyboardType="numeric"
onChangeText={text => handleOnchange(text, 'phone')}
onFocus={() => handleError(null, 'phone')}
iconName="phone-outline"
label="Phone Number"
placeholder="Enter your phone no"
error={errors.phone}
defaultValue={phone}
/>
<Button title="Save" onPress={validate} />
<Button title="Cancel" onPress={() => props.navigation.navigate("List")} />
</View>
</ScrollView>
</SafeAreaView>
);
};
export default EditScreen;
This is The Error
enter image description here
Your 'Edit' navigator is declared in your Edit() function but the function is never called.
react-navigation does know how to navigate to it since it is never initiated
You should try to call the function at least once at component start so the navigator is initiated
You do not have EditScreen as a screen on the drawers navigation screens in App.js
Try to add:
<Drawer.Screen name="Edit" component={EditScreen} />
On App.js

TypeError: text.toLowerCase is not a function. (In 'text.toLowerCase()', 'text.toLowerCase' is undefined)

I am doing a project using MERN STACK in this I faced the above error.
ProductContainer.js
import React, { useState, useEffect } from 'react'
import { View, StyleSheet, ActivityIndicator, FlatList, Text} from 'react-native'
import { Container, Header, Icon, Item, Input } from 'native-base';
import ProductList from './ProductList';
import SearchedProduct from './SearchedProducts';
const data = require('../../assets/data/products.json');
const ProductContainer = () => {
const [products, setProducts ] = useState([]);
const [productsFiltered, setProductsFiltered] = useState([]);
const [focus, setFocus] = useState();
useEffect(() => {
setProducts(data);
setProductsFiltered(data);
setFocus(false);
return () => {
setProducts([])
setProductsFiltered([])
setFocus()
}
}, [])
const SearchProduct = (text) => {
setProductsFiltered(
products.filter((i) => i.name.toLowerCase().includes(text.toLowerCase()))
);
};
const openList = () => {
setFocus(true);
};
const onBlur = () => {
setFocus(flase);
};
return (
<Container>
<View style = {{ flexDirection: "row"}}>
<Input
width = "100%"
variant = "rounded"
placeholder="Search"
onFocus={openList}
onChangeText={(text) => SearchProduct(text)}
/>
</View>
{focus == true ? (
<SearchProduct
productsFiltered={productsFiltered}
/>
) : (
<View style={styles.container}>
<Text>Product Container</Text>
<View style={styles.listContainer}>
<FlatList
data={products}
numColumns={2}
renderItem={({item}) => <ProductList
key={item.brand}
item={item}/>}
keyExtractor={item => item.brand}
/>
</View>
</View>
)}
</Container>
)
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
export default ProductContainer
SearchedProducts.js
import React from 'react';
import { View, StyleSheet, Dimensions} from 'react-native'
import { Content, Left, Body, ListItem, Thumbnail, Text } from 'native-base';
const SearchedProduct = (props) => {
const { productsFiltered } = props;
return(
<Content >
{productsFiltered.length > 0 ? (
productsFiltered.map((item) => (
<ListItem
key={item._id.$oid}
avatar
>
<Left>
<Thumbnail
source={{uri: item.image ?
item.image : 'https://cdn.pixabay.com/photo/2012/04/01/17/29/box-23649_960_720.png'
}}
/>
</Left>
<Body>
<Text>{item.name}</Text>
<Text note>{item.description}</Text>
</Body>
</ListItem>
))
) : (
<View style={styles.center}>
<Text style={{ alignSelf: 'center' }}>
No products match the selected criteria
</Text>
</View>
)}
</Content>
);
};
const styles = StyleSheet.create({
center: {
justifyContent: 'center',
alignItems: 'center',
height: 100
}
})
export default SearchedProduct;
Please can anyone help me to solve this error .If you want I will provide other details of my code.
Thanks in advance
Not sure but you are using SearchProduct name as a component and at the same time as a method. Maybe try to rename changing either component name or method name to see if it works.

i should click twice to get my page [react typescript pagination]

I'm using asp.net core and react typescript and I would like to use paginatedEntity from my API and use it to create pagination in react. Any leads, please?
Below is the code:
import { Card, CardActionArea } from "#material-ui/core";
import { observer } from "mobx-react-lite";
import { useEffect, useState } from "react";
import { Grid, Item } from "semantic-ui-react";
import LoadingComponent from "../../app/layout/LoadingComponent";
import { PagingParams } from "../../app/stores/pagination";
import { useStore } from "../../app/stores/store";
import { makeStyles, createStyles } from '#material-ui/core/styles';
import Pagination from '#material-ui/lab/Pagination';
import React from "react";
const useStyles = makeStyles((theme) =>
createStyles({
root: {
'& > * + *': {
marginTop: theme.spacing(2),
},
},
}),
);
export default observer(function AllProduct() {
const { productStore } = useStore();
const [, setLoadingPage] = useState(false);
const classes = useStyles();
const [page, setPage] = React.useState(1);
const handleChange = (_event: React.ChangeEvent<unknown>, value: number) => {
setPage(value);
};
function handleGetPage() {
setLoadingPage(true);
productStore.setPagingParams(new PagingParams(page));
productStore.loadProducts().then(() => setLoadingPage(false));
}
useEffect(() => {
productStore.loadProducts();
}, [productStore])
if (productStore.loadingInitial) return <LoadingComponent />
return (
<Grid style={{ marginTop: '7em' }}>
<Grid.Column width='5' id='FilterHeightSide'>
</Grid.Column>
<Grid.Column width='10'>
<div className={classes.root}>
{
productStore.products.map((product: any) =>
<Grid.Column key={product.id} width='10'>
<Card>
<CardActionArea >
<Item.Group>
<Item>
<Item.Image id='MainPhotoItems' style={{ marginLeft: '1em', marginTop: '1em' }} src={product.mainPhotoUrl} />
<Item.Content>
<Item.Header style={{ marginTop: '0.5em' }}>{product.productName}</Item.Header>
<Item.Meta style={{ marginTop: '1.5em' }}>
<span id="TextPrice" className='price'>${product.priceIncTax}</span>
<span className='stay'></span>
</Item.Meta>
<Item.Description><img src={product.brandPhotoUrl} alt="brand"
id="LogoBrandItem" /></Item.Description>
</Item.Content>
</Item>
</Item.Group>
</CardActionArea>
</Card>
</Grid.Column>
)
}
<Pagination count={productStore.totalPages} onChange={handleChange} onClick=
{handleGetPage} page={page} />
</div>
</Grid.Column>
</Grid>
)
})
I'm using asp.net core and react typescript and I would like to use paginatedEntity from my API and use it to create pagination in react. Any leads, please?
Well i finally find the solution :
import { Card, CardActionArea } from "#material-ui/core";
import { observer } from "mobx-react-lite";
import { useEffect, useState } from "react";
import { Grid, Item } from "semantic-ui-react";
import LoadingComponent from "../../app/layout/LoadingComponent";
import { PagingParams } from "../../app/stores/pagination";
import { useStore } from "../../app/stores/store";
import { makeStyles, createStyles } from '#material-ui/core/styles';
import Pagination from '#material-ui/lab/Pagination';
import React from "react";
const useStyles = makeStyles((theme) =>
createStyles({
root: {
'& > * + *': {
marginTop: theme.spacing(2),
},
},
}),
);
export default observer( function AllProduct(){
const {productStore }=useStore();
const [, setLoadingPage] = useState(false);
const classes = useStyles();
const [page, setPage] = React.useState(1);
const handleChange = (_event: React.ChangeEvent<unknown>, value: number) => {
setLoadingPage(true);
productStore.setPagingParams(new PagingParams(productStore.pagingParams.pageNumber=value));
productStore.loadProducts().then(()=>setPage(value)).then(() => setLoadingPage(false));
};
useEffect(()=> {
productStore.loadProducts();
},[productStore])
if(productStore.loadingInitial ) return <LoadingComponent/>
return(
<Grid style={{marginTop:'8em'}}>
<Grid.Column width='5' id='FilterHeightSide'>
</Grid.Column>
<Grid.Column width='10'>
<div className={classes.root}>
{
productStore.products.map((product:any)=>
<Grid.Column key={product.id} width='10'>
<Card>
<CardActionArea >
<Item.Group>
<Item>
<Item.Image id='MainPhotoItems' style={{marginLeft:'1em' , marginTop:'1em'}} src={product.mainPhotoUrl} />
<Item.Content>
<Item.Header style={{marginTop:'0.5em'}}>{product.productName}</Item.Header>
<Item.Meta style={{marginTop:'1.5em'}}>
<span id="TextPrice" className='price'>${product.priceIncTax}</span>
<span className='stay'></span>
</Item.Meta>
<Item.Description><img src={product.brandPhotoUrl} alt="brand" id="LogoBrandItem" /></Item.Description>
</Item.Content>
</Item>
</Item.Group>
</CardActionArea>
</Card>
</Grid.Column>
)
}
<Pagination count={productStore.totalPages} page={page} onChange={handleChange} />
</div>
</Grid.Column>
</Grid>
)
})
i hope that will help others :)

Next js: Error: Objects are not valid as a React child (found: Error: Response not successful: Received status code 401)

This app shows Github issues with graphql API.
I didn't change anything after finishing the app but I got this error.
I used Next js, Typescript, Material UI, Tailwind css and GraphQL for this project.
Index Component
import React, { useState } from "react"
import { Typography, Container, makeStyles } from "#material-ui/core"
import SearchBar from "../components/SearchBar/SearchBar"
import RepositoryList from "../components/RepositoryList/RepositoryList"
import Head from "next/head"
const useStyles = makeStyles({
title: {
marginTop: "1rem",
marginBottom: "1rem",
textAlign: "center",
},
})
const App = () => {
const classes = useStyles()
const [searchTerm, setSearchTerm] = useState<string>("")
return (
<>
<Head>
<title>GraphQL Github Client</title>
</Head>
<Container maxWidth={"sm"}>
<div className="mt-10 mb-5">
<Typography variant={"h3"} className={classes.title}>
GraphQL Github Client
</Typography>
</div>
<SearchBar
className="mb-10"
value={searchTerm}
onChange={setSearchTerm}
/>
<RepositoryList searchTerm={searchTerm} />
</Container>
</>
)
}
export default App
RepositoryList Component
import React, { useEffect, useState } from "react"
import { Typography, CircularProgress, makeStyles } from "#material-ui/core"
import { useQuery } from "#apollo/react-hooks"
import { SEARCH_FOR_REPOS } from "../../Queries/queries"
import Repository from "../Repository/Repository"
interface RepositoryListProps {
searchTerm?: string
}
const useStyles = makeStyles({
note: {
marginTop: "1rem",
textAlign: "center",
},
spinnerContainer: {
display: "flex",
justifyContent: "space-around",
marginTop: "1rem",
},
})
const RepositoryList: React.FC<RepositoryListProps> = ({ searchTerm }) => {
const classes = useStyles()
const [expandedRepo, setExpandedRepo] = useState(null)
const { data, loading, error } = useQuery(SEARCH_FOR_REPOS, {
variables: { search_term: searchTerm },
})
useEffect(() => {
setExpandedRepo(null)
}, [data])
if (loading) {
return (
<div className={classes.spinnerContainer}>
<CircularProgress />
</div>
)
}
if (error) {
return (
<Typography
variant={"overline"}
className={classes.note}
component={"div"}
color={"error"}
>
{error}
</Typography>
)
}
if (!data.search.repositoryCount) {
return (
<Typography
variant={"overline"}
className={classes.note}
component={"div"}
>
There are no such repositories!
</Typography>
)
}
return (
<div>
{data.search.edges.map(
(
repo: { edges: { id: number } },
i: string | number | ((prevState: null) => null) | null | any
) => (
<>
<Repository
repo={repo}
expanded={expandedRepo === i}
onToggled={() => setExpandedRepo(i)}
key={repo.edges.id}
/>
</>
)
)}
</div>
)
}
export default RepositoryList
Repository Component
import React from "react"
import {
ExpansionPanel,
ExpansionPanelSummary,
ExpansionPanelDetails,
Typography,
Chip,
makeStyles,
} from "#material-ui/core"
import StarIcon from "#material-ui/icons/Star"
import PeopleIcon from "#material-ui/icons/People"
import IssueList from "../IssueList/IssueList"
const useStyles = makeStyles({
root: {
marginTop: "1rem",
},
summaryContainer: {
flexDirection: "column",
},
summaryHeader: {
display: "flex",
flexDirection: "row",
justifyContent: "space-between",
marginBottom: "1rem",
},
chip: {
marginLeft: "0.5rem",
},
})
interface RepositoryProps {
repo: any
expanded: boolean
onToggled: any
}
const Repository: React.FC<RepositoryProps> = ({
repo,
expanded,
onToggled,
}) => {
const {
node: {
name,
descriptionHTML,
owner: { login },
stargazers: { totalCount: totalStarCount },
},
} = repo
const classes = useStyles()
return (
<ExpansionPanel
expanded={expanded}
onChange={onToggled}
className={classes.root}
>
<ExpansionPanelSummary classes={{ content: classes.summaryContainer }}>
<div className={classes.summaryHeader}>
<Typography variant={"h6"}>{name}</Typography>
<div>
<Chip
label={`by ${login}`}
avatar={<PeopleIcon />}
className={classes.chip}
/>
<Chip
label={totalStarCount}
avatar={<StarIcon />}
className={classes.chip}
/>
</div>
</div>
<Typography
variant={"caption"}
dangerouslySetInnerHTML={{ __html: descriptionHTML }}
component={"div"}
/>
</ExpansionPanelSummary>
<ExpansionPanelDetails>
{expanded && <IssueList repoName={name} repoOwner={login} />}
</ExpansionPanelDetails>
</ExpansionPanel>
)
}
export default Repository
These are my components.
What should I do for fixing this problem?
It looks like the issue is in this spot where you do {error}. I would double check what error actually is but it looks like its an object and not a string like you are using it
<Typography
variant={"overline"}
className={classes.note}
component={"div"}
color={"error"}
>
{error}
</Typography>

Login not going to HomeScreen

My login not going to HomeScreen, but when I reload the app it will automatically go to HomeScreen? The login functionality works fine the only thing that bugging me right now, it needs to reload the app before it will go to HomeScreen.
Below are the file for my App, LoadingScreen, LoginScreen, and HomeScreen.
App.js
import React, { useEffect, useState } from 'react';
import { NavigationContainer } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
import SignupScreen from './screens/SignupScreen';
import LoginScreen from './screens/LoginScreen';
import LoadingScreen from './screens/LoadingScreen';
import HomeSceen from './screens/HomeScreen';
import AsyncStorage from '#react-native-community/async-storage';
const App = ({ navigation }) => {
const [isloggedin, setLogged] = useState(null);
const detectLogin = async () => {
const token = await AsyncStorage.getItem('token');
if (token !== null) {
setLogged(true);
} else {
setLogged(false);
}
};
useEffect(() => {
detectLogin();
}, []);
const StackApp = createStackNavigator();
return (
<NavigationContainer>
<StackApp.Navigator headerMode="none">
<StackApp.Screen name="loading" component={LoadingScreen} />
<StackApp.Screen name="home" component={HomeSceen} />
<StackApp.Screen name="login" component={LoginScreen} />
<StackApp.Screen name="signup" component={SignupScreen} />
</StackApp.Navigator>
</NavigationContainer>
);
}
export default App;
LoadingScreen.js
import React, { useEffect } from 'react';
import {
ActivityIndicator,
View,
StyleSheet
} from 'react-native';
import AsyncStorage from '#react-native-community/async-storage';
const LoadingScreen = (props) => {
const detectLogin = async () => {
const token = await AsyncStorage.getItem('token');
if (token) {
props.navigation.replace("home");
} else {
props.navigation.replace("login");
}
};
useEffect(() => {
detectLogin();
}, []);
return (
<View style={styles.loading}>
<ActivityIndicator size="large" color="#ff0550" />
</View>
);
};
const styles = StyleSheet.create({
loading: {
flex: 1,
justifyContent: "center",
alignItems: "center"
},
});
export default LoadingScreen;
LoginScreen.js
import React, { useState } from 'react';
import { Button, TextInput } from 'react-native-paper';
import {
View,
Text,
StatusBar,
TouchableOpacity,
KeyboardAvoidingView,
Alert,
} from 'react-native';
import AsyncStorage from '#react-native-community/async-storage';
import { SafeAreaView } from 'react-native-safe-area-context';
const LoginScreen = (props) => {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const handleLogin = async (props) => {
fetch('http://localhost:3000/api/auth/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
'email': email,
'password': password,
}),
})
.then(res => res.json())
.then(async (data) => {
try {
const items = [['token', data.token], ['user', data.user._id]];
AsyncStorage.multiSet(items);
props.navigation.replace('home');
} catch (e) {
console.log('error log', data.error);
Alert(data.error);
}
});
};
return (
<SafeAreaView style={{ flex: 1 }}>
<KeyboardAvoidingView behavior="position">
<StatusBar backgroundColor="#ff0550" barStyle="light-content" />
<View
style={{
borderBottomColor: '#ff0550',
borderBottomWidth: 4,
borderRadius: 10,
marginLeft: 20,
marginRight: 150,
marginTop: 4,
}}
/>
<Text
style={{
fontSize: 20, marginLeft: 18, marginTop: 20
}}
>Login with email</Text>
<TextInput
label='Email'
autoCapitalize="none"
mode="outlined"
value={email}
style={{ marginLeft: 18, marginRight: 18, marginTop: 18 }}
theme={{ colors: { primary: '#ff0550' } }}
onChangeText={(text) => setEmail(text)}
/>
<TextInput
label='password'
autoCapitalize="none"
mode="outlined"
secureTextEntry={true}
value={password}
onChangeText={(text) => { setPassword(text) }}
style={{ marginLeft: 18, marginRight: 18, marginTop: 18 }}
theme={{ colors: { primary: '#ff0550' } }}
/>
<Button
mode="contained"
style={{ marginLeft: 18, marginRight: 18, marginTop: 18, backgroundColor: '#ff0550' }}
onPress={() => handleLogin(props)}>
Login
</Button>
<TouchableOpacity>
<Text
style={{
fontSize: 18, marginLeft: 18, marginTop: 20
}}
onPress={() => props.navigation.replace('signup')}
>dont have a account ?</Text>
</TouchableOpacity>
</KeyboardAvoidingView>
</SafeAreaView>
);
};
export default LoginScreen;
HomeScreen.js
import React, { useEffect, useState } from 'react';
import { Button } from 'react-native-paper';
import { Text, View } from 'react-native';
import AsyncStorage from '#react-native-community/async-storage';
const HomeScreen = (props) => {
const logout = (props) => {
let keys = ['user', 'token'];
AsyncStorage.multiRemove(keys, (error) => {
props.navigation.replace('login');
});
};
return (
<View style={{ flex: 1, marginTop: 100 }}>
<Text style={{ fontSize: 18 }}>your email is sample here!</Text>
<Button
mode="contained"
style={{ marginLeft: 18, marginRight: 18, marginTop: 18, backgroundColor: '#ff0550' }}
onPress={() => logout(props)}
>
logout
</Button>
</View>
);
};
export default HomeScreen;
user props.navigation.navigate("Homescreen")
Also,you need add condition in app js if logged then go to homescreen else login page.
Check switch Navigator too from react-navigation
Replace just change current screen to another screen instead of navigating through screen. so it will stay that screen only

Resources