Ways to stop re-rendering when a state is changed ? (React Native) - javascript

Let me summarize a lil bit, what I'm trying to do is when the news is clicked, a modal (in this case I used a library: react-native-modalize https://github.com/jeremybarbet/react-native-modalize) is presented with the respective details of the clicked news
In order for the content inside the modal to be dynamic, I used states to store the details, so whenever a click is registered on the news, a series of details is passed thru function parameters and store in the respective state
THE PROBLEM is that whenever a state on the top level is changed the whole component refresh itself, and it's causing problem like:
Scenario 1: when the user scroll until the end of the scroll view and pressed on one of the news, modal is brought up and because the state is being changed, the whole app refreshes and the scroll view jumps back to the top.
app.js
import { StatusBar } from 'expo-status-bar';
import React from 'react';
import { useRef, useState, useEffect } from 'react';
import { AppLoading } from 'expo'
import { StyleSheet, Text, View, FlatList, SafeAreaView, ScrollView, Image, TouchableOpacity } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
import { Modalize } from 'react-native-modalize';
import { Ionicons } from '#expo/vector-icons';
import { render } from 'react-dom';
import Header from './components/Header';
import NuaDaily from './components/Daily';
import Content from './components/Content';
import moment from "moment";
const HomeStackScreen = () => {
const [title, setTitle] = useState([])
const [author, setAuthor] = useState([])
const [publication, setPublication] = useState([])
const [imageUrl, setImageUrl] = useState([])
const [summary, setSummary] = useState([])
const modalizeRef = useRef(null);
const onOpen = (title, author, publication, imageUrl, summary) => {
modalizeRef.current?.open();
setTitle(title)
setAuthor(author)
setPublication(publication)
setImageUrl(imageUrl)
setSummary(summary)
};
return (
<>
<SafeAreaView style={styles.container}>
<ScrollView style={styles.scrollView}>
<View style={styles.container}>
<Header />
<NuaDaily modalize={onOpen} style={styles.nuadaily} />
<Content modalize={onOpen} />
</View>
</ScrollView>
</SafeAreaView>
<Modalize snapPoint={650} modalTopOffset={10} ref={modalizeRef} style={{ width: '100%', alignItems: 'center', justifyContent: 'center', padding: 20 }}>
<View style={{padding: 20}}>
<Image
style={{width: 350, height: 200, zIndex: 1000, borderRadius: 8, marginTop: 10}}
source={{ uri: `${imageUrl}` }}
/>
<Text style={styles.modalTitle}>{title}</Text>
<View style={styles.detailsBar}>
<Text style={styles.modalAuthor}>{author}</Text>
<Text style={styles.modalPublication}>{moment(publication).format("MM-DD-YYYY")}</Text>
</View>
<Text style={styles.modalSummary}>{summary}</Text>
</View>
</Modalize>
</>
)
}
const Tab = createBottomTabNavigator();
export default function App() {
return (
<NavigationContainer>
<Tab.Navigator
tabBarOptions={
{
activeTintColor: '#00B2FF',
inactiveTintColor: 'gray',
showLabel: false,
style: { height: 60, borderRadius: 0, backgroundColor: 'rgba(255, 255, 255, 0.85)'}
}
}
showLabel = {false}
screenOptions={({ route }) => ({
tabBarIcon: ({ focused, color, size }) => {
if (route.name === 'Home') {
return <HomeIcon />
}
},
})}
>
<Tab.Screen name="Home"
component={
HomeStackScreen
} />
</Tab.Navigator>
</NavigationContainer>
);
}
});
Daily (index.js) (imported on app.js)
import React from 'react';
import { useState, useEffect } from 'react';
import {View, Text, FlatList, Image, ImageBackground, ScrollView, SafeAreaView, TouchableOpacity} from 'react-native';
import axios from 'axios';
import moment from "moment";
import * as Font from 'expo-font';
import AppLoading from 'expo-app-loading';
import { useFonts } from 'expo-font';
import styles from './style';
import Dot from '../../assets/images/dot.svg';
const nuaDaily = ( props ) => {
const Item = ({ title, author, publication, imageUrl, summary }) => (
<View style={styles.item}>
<TouchableOpacity onPress={()=>props.modalize(title, author, publication, imageUrl, summary)}>
<Image
style={{width: 210, height: 200, zIndex: 1000, borderRadius: 8, marginTop: 10}}
source={{ uri: `${imageUrl}` }}
/>
<Text style={ [styles.title, {fontFamily: 'Poppins'}]}>{title}</Text>
<View style={styles.bottomBar}>
<Text style={styles.author}>{author}</Text>
<Text style={styles.publication}>{moment(publication).format("MM-DD-YYYY hh:mm")}</Text>
</View>
</TouchableOpacity>
</View>
);
const renderItem = ({ item }) => {
if(moment(item.publication).isSame(moment(), 'day')){
return <Item title={item.title} author={item.newsSite} publication={item.publishedAt} imageUrl={item.imageUrl} summary={item.summary} />
}else{
// return <Item title={item.title} author={item.newsSite} publication={item.publishedAt} imageUrl={item.imageUrl} summary={item.summary} />
}
};
const [data, setData] = useState([])
useEffect(() => {
axios.get(APIURL)
.then((res) => {
setData(res.data)
})
.catch((err) => {
console.log(`error calling API ${err}`)
})
},[])
return (
<View style={styles.container}>
<View style={styles.containerTitle}>
<Dot style={styles.dot} />
<Text style={ [styles.PrimaryText , {fontFamily: 'Quicksand'}]}>NUA Daily</Text>
</View>
<FlatList
showsHorizontalScrollIndicator={false}
horizontal={true}
data={data}
renderItem={renderItem}
style={styles.flatList}
/>
</View>
)
}
export default nuaDaily;
Demo of the problem (Scenario 1)

Related

react native hover effect module not working properly in dynamic

I trying to make a onPress hover effect to show text, when I click on image it will show me a text layer on my image, as its working fine for one image & text, but while making dynamic.. clicked on one image then that effect, affecting to all images with text.
simply I want to show on single click show one text related to img, on different images on click show different text related to that images.
how can fix it..
App.js
import Button from "../custom-components/Button";
import React, { useState, useEffect } from "react";
import {
Image,
ImageBackground,
StyleSheet,
TouchableOpacity,
Text,
Touchable,
View,
FlatList,
} from "react-native";
import { ScrollView } from "react-native-gesture-handler";
import { BottomTabBarHeightCallbackContext } from "#react-navigation/bottom-tabs";
import axios from "axios";
import { API_URL } from "#env";
import { useSelector } from "react-redux";
export default function App() {
const languageState = useSelector((state) => state.languageReducer);
const [xx43d, setxx43d] = React.useState(languageState.language);
const [showText, setShowText] = useState(false);
const [apiData, setApiData] = useState([]);
React.useEffect(() => {
axios
.get(`${API_URL}/xyxsnn?xx43d=${xx43d}`)
.then((response) => {
if (response.status === 200) {
setApiData(response.data.result);
}
})
.catch((errors) => {
console.log(errors);
});
}, []);
return (
<>
<ScrollView>
<FlatList
data={apiData}
numColumns={2}
keyExtractor={(item, index) => index}
renderItem={({ item }) => (
<>
<TouchableOpacity
activeOpacity={0.5}
onPress={() => setShowText(!showText)}
>
<ImageBackground
source={{ uri: "https://reactjs.org/logo-og.png" }}
resizeMode="cover"
style={styles.image}
>
{!!showText && <Text style={styles.text}>{item.name}</Text>}
</ImageBackground>
</TouchableOpacity>
</>
)}
/>
</ScrollView>
</>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
image: {
justifyContent: "center",
height: 250,
width: 170,
margin: 12,
borderRadius: 10,
},
text: {
color: "white",
fontSize: 20,
fontWeight: "bold",
textAlign: "center",
backgroundColor: "#000",
},
});
Make Item a seprate component which has its own showText state.
Like
import Button from "../custom-components/Button";
import React, { useState, useEffect } from "react";
import {
Image,
ImageBackground,
StyleSheet,
TouchableOpacity,
Text,
Touchable,
View,
FlatList,
} from "react-native";
import { ScrollView } from "react-native-gesture-handler";
import { BottomTabBarHeightCallbackContext } from "#react-navigation/bottom-tabs";
import axios from "axios";
import { API_URL } from "#env";
import { useSelector } from "react-redux";
export default function App() {
const languageState = useSelector((state) => state.languageReducer);
const [xx43d, setxx43d] = React.useState(languageState.language);
const [apiData, setApiData] = useState([]);
React.useEffect(() => {
axios
.get(`${API_URL}/xyxsnn?xx43d=${xx43d}`)
.then((response) => {
if (response.status === 200) {
setApiData(response.data.result);
}
})
.catch((errors) => {
console.log(errors);
});
}, []);
return (
<>
<ScrollView>
<FlatList
data={apiData}
numColumns={2}
renderItem={({ item }) => <Item data={item}/>}
keyExtractor={(item, index) => index}
/>
</ScrollView>
</>
);
}
const Item = ({data}) => {
const [showText, setShowText] = useState(false);
return(<TouchableOpacity
activeOpacity={0.5}
onPress={() => setShowText(!showText)}
>
<ImageBackground
source={{ uri: "https://reactjs.org/logo-og.png" }}
resizeMode="cover"
style={styles.image}
>
{showText && <Text style={styles.text}>{data.name}</Text>}
</ImageBackground>
</TouchableOpacity>)
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
image: {
justifyContent: "center",
height: 250,
width: 170,
margin: 12,
borderRadius: 10,
},
text: {
color: "white",
fontSize: 20,
fontWeight: "bold",
textAlign: "center",
backgroundColor: "#000",
},
});

undefined is not an object (evaluating 'navigation.navigate') when trying to navigate to a file that will open camera on the phone

I'm trying to navigate to my page "CameraPage.js" but I'm getting this error "undefined is not an object (evaluating 'navigation.navigate')". Can anybody see the problem? This ismy first question here so please tell me if I can be more specific.
Here's my App.js:
import { StyleSheet, Text, View, TouchableOpacity, Pressable } from 'react-native';
import React, {useEffect, useState} from "react";
import { FontAwesome } from '#expo/vector-icons';
import { useNavigation } from '#react-navigation/native';
export default function App({ navigation }) {
return (
<View style={styles.container}>
<View style={styles.buttonContainer}>
<TouchableOpacity onPress ={() => navigation.navigate('CameraFunction')}>
<FontAwesome name="camera" size={100} color="#FFB6C1" />
</TouchableOpacity>
<Pressable>
<FontAwesome name="photo" size={100} color="#FFB6C1" />
</Pressable>
</View>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#FFDBE9'
},
buttonContainer: {
backgroundColor: 'transparent',
justifyContent: 'space-between',
},
});
Here is my CameraPage.js file:
import {StyleSheet, Text, View, TouchableOpacity} from 'react-native';
import {Camera, CameraType} from 'expo-camera';
import {useEffect, useState} from "react";
export default function CameraPage() {
const [hasPermission, setHasPermission] = useState(null);
const [type, setType] = useState(CameraType.back);
useEffect(() => {
(async () => {
const {status} = await Camera.requestCameraPermissionsAsync();
setHasPermission(status === 'granted');
})();
}, []);
if (hasPermission === null) {
return <View/>;
}
if (hasPermission === false) {
return <Text>No access to camera</Text>;
}
return (
<View style={styles.container}>
<Camera style={styles.camera} type={type}>
<View style={styles.buttonContainer}>
<TouchableOpacity
style={styles.button}
onPress={() => {
setType(type === CameraType.back ? CameraType.front : CameraType.back);
}}>
<Text style={styles.text}> Flip </Text>
</TouchableOpacity>
</View>
</Camera>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
camera: {
flex: 1,
},
buttonContainer: {
flex: 1,
backgroundColor: 'transparent',
flexDirection: 'row',
margin: 20,
},
button: {
flex: 0.1,
alignSelf: 'flex-end',
alignItems: 'center',
},
text: {
fontSize: 18,
color: 'white',
},
});
Here is my navigation file:
import React from 'react';
import {createStackNavigator} from '#react-navigation/stack';
import {NavigationContainer} from '#react-navigation/native';
import CameraPage from "../Camera/CameraPage";
const Routes = createStackNavigator();
export default function Navigator() {
return (
<NavigationContainer>
<Routes.Navigator>
<Routes.Screen
name="CameraFunction"
component={CameraPage}
/>
</Routes.Navigator>
</NavigationContainer>
);
}
Your navigation container must be wrapped around the root of your application or otherwise the navigation object will not be passed to the components that you have defined as screens.
The following fixes your issue.
export default const App = () => {
return (
<NavigationContainer>
<Routes.Navigator>
<Routes.Screen name="Home" component={HomeScreen} />
<Routes.Screen
name="CameraFunction"
component={CameraPage}
/>
</Routes.Navigator>
</NavigationContainer>
);
}
Your HomeScreen contains the old code from App, but now you can access the navigation object since we have defined HomeScreen as a screen inside the navigator. It will be passed to that screen by the navigation framework. Notice as well that HomeScreen is the initial screen of your application.
export default function HomeScreen({ navigation }) {
return (
<View style={styles.container}>
<View style={styles.buttonContainer}>
<TouchableOpacity onPress ={() => navigation.navigate('CameraFunction')}>
<FontAwesome name="camera" size={100} color="#FFB6C1" />
</TouchableOpacity>
<Pressable>
<FontAwesome name="photo" size={100} color="#FFB6C1" />
</Pressable>
</View>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#FFDBE9'
},
buttonContainer: {
backgroundColor: 'transparent',
justifyContent: 'space-between',
},
});
Notice, that you need to navigate back to the HomeScreen once you have navigated to the CameraPage. You can use the navigation object in the CameraPage as well and trigger navigation.goBack to achieve this effect.
You just use #react-navigation/native-stack in place of #react-navigation/stack in App.js file then it will working perfect ,
import * as React from 'react';
import {NavigationContainer} from '#react-navigation/native';
import {createNativeStackNavigator} from '#react-navigation/native-stack';
import Home from './TopTabBar/Home';
import 'react-native-gesture-handler';
const Stack = createNativeStackNavigator();
function App() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Home" component={Home} />
</Stack.Navigator>
</NavigationContainer>
);
}
export default App;

Navigation, not working from Pulled functions

I will try to explain this as best I can, I'm still new and have a hard time understanding the terminology.
I am working on a react native project. I have created two files. One Header.js and one footer.js.
I have successfully pulled them in to my Home Screen. However the buttons, inside footer.js, no longer fires. I get; undefined is not an object (evaluating 'navigation.navigate') for the error.
How do I bring back the functionality?
Any help is very appreciated. Here is my project to help;
App.js
import React from 'react';
import TabNavigator from "./assets/component/TabNavigator";
import {StackNavigation} from "./assets/component/StackNavigation";
export default function App() {
return (
<StackNavigation/>
);
}
StackNavigation.js;
import React from 'react';
import { HomeScreen} from "../Screens/HomeScreen";
import LayoutProps from "../Screens/Layout Props";
import SampleViewProps from "../Screens/SampleViewProps";
import {NavigationContainer} from "#react-navigation/native";
import {createNativeStackNavigator} from "#react-navigation/native-stack";
// import ShareExample from "./assets/component/SBShare";
const Stack = createNativeStackNavigator();
export function StackNavigation() {
return (
<NavigationContainer>
<Stack.Navigator initialRouteName="Home">
<Stack.Screen name="Home" component={HomeScreen}/>
<Stack.Screen name="Layout Props" component={LayoutProps} />
<Stack.Screen name="View Props" component={SampleViewProps} />
</Stack.Navigator>
</NavigationContainer>
);
}
HomeScreen.js;
import React from 'react';
import {Button, View, SafeAreaView, StyleSheet} from 'react-native';
import HeaderSB from "../component/SBHeader";
import FooterSB from "../component/SBFooter";
// import ShareExample from "./assets/component/SBShare";
export function HomeScreen({navigation}) {
const receiveValue = (value) => {
console.log("value received from B", value)
}
return (
<>
<SafeAreaView style={styles.container}>
<View style={styles.headerContainer}>
<HeaderSB receiveValue={receiveValue}>
</HeaderSB>
</View>
<View style={styles.mainContent}>
<View style={styles.buttonBox}>
<Button onPress={() => navigation.navigate('Layout Props')} title="Layout Props"/>
<Button onPress={() => navigation.navigate('View Props')} title="View Style Props"/>
</View>
</View>
<View styles={styles.footerContainer}>
<FooterSB receiveValue={receiveValue}>
</FooterSB>
</View>
</SafeAreaView>
</>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: "space-between",
},
headerContainer: {
},
mainContent: {
},
buttonBox: {}
,
footerContainer: {
},
});
Footer.js;
import * as React from "react";
import {StyleSheet, TouchableOpacity, View} from "react-native";
import {AntDesign, Feather} from "#expo/vector-icons";
import {StackNavigation} from "./StackNavigation";
const FooterSB = ({navigation}) => {
return (
<>
{/* Bottom App Navigation */}
<View style={footerStyle.navCon}>
<View style={footerStyle.navBar}>
{/* Home Button */}
<TouchableOpacity style={footerStyle.home} onPress={() =>
navigation.navigate('Home')}
>
{/* Icon */}
<AntDesign name="home" size={50} color="white"/>
</TouchableOpacity>
{/* Navigation Divider */}
<View style={footerStyle.navDivider}/>
{/* Setting Button */}
<TouchableOpacity style={footerStyle.settings} onPress={() =>
navigation.navigate('Layout Props')}
>
{/* Icon */}
<Feather name="settings" size={50} color="white"/>
</TouchableOpacity>
</View>
</View>
</>
);
}
const footerStyle = StyleSheet.create({
navCon: {
flex: 1,
marginTop: 20,
alignItems: "center",
justifyContent: "flex-end"
},
navBar: {
flexDirection: "row",
justifyContent: "space-evenly",
alignItems: "center",
backgroundColor: "#808080",
width: 500,
height: 50,
},
home: {
// paddingHorizontal: 55,
},
navDivider: {
backgroundColor: "#FFF",
width: 4,
height: 50,
},
settings: {
// marginRight: 107,
// paddingHorizontal: 55,
},
});
export default FooterSB;
If you want navigation as default prop you should add it as <Stack.Screen> but as FooterSB is custom and individual component it doesn't get wrapped with navigation prop automatically.
You need to pass navigation as prop to that so change below
<FooterSB receiveValue={receiveValue}>
</FooterSB>
to
<FooterSB receiveValue={receiveValue} navigation={navigation}>
</FooterSB>
Same way you can pass navigation to header too.

React Native NavigationContainer not displaying anything

I'm having an issue using React Native with React Navigator where I'm not seeing a navigation menu at all. I'm using the following code:
App.js:
import "react-native-gesture-handler";
import React from "react";
import { StyleSheet, View } from "react-native";
import { QUATERNARY_COLOR } from "./env.json";
import Header from "./components/header";
import Routes from "./components/routes";
const App = () => {
return (
<View style={styles.home}>
<Header />
<Routes style={styles.routes} />
</View>
);
};
const styles = StyleSheet.create({
home: {
flex: 1,
backgroundColor: QUATERNARY_COLOR,
alignItems: "center",
paddingTop: 60,
},
});
export default App;
Header.js:
import React from "react";
import { StyleSheet, Text, View, Dimensions } from "react-native";
import { APP_NAME, PRIMARY_COLOR, QUATERNARY_COLOR } from "../env.json";
var width = Dimensions.get("window").width;
const Header = () => {
return (
<View style={styles.header}>
<Text style={styles.text}>{APP_NAME}</Text>
</View>
);
};
const styles = StyleSheet.create({
header: {
height: 48,
padding: 8,
paddingRight: 12,
paddingLeft: 12,
backgroundColor: PRIMARY_COLOR,
position: "absolute",
top: 24,
width: width,
alignSelf: "stretch",
textAlign: "center",
},
text: {
color: QUATERNARY_COLOR,
fontSize: 23,
fontWeight: "bold",
textAlign: "center",
},
});
export default Header;
Routes.js:
import React from "react";
import { Text, View } from "react-native";
import { NavigationContainer } from "#react-navigation/native";
import { createStackNavigator } from "#react-navigation/stack";
import Home from "../pages/home";
import Login from "../pages/login";
const Stack = createStackNavigator();
const Routes = () => {
return (
<React.Fragment>
<NavigationContainer>
<Stack.Navigator style={{ flex: 1 }}>
<Stack.Screen
name="Home"
component={Home}
options={{ title: "Home" }}
/>
<Stack.Screen name="Login" component={Login} />
</Stack.Navigator>
</NavigationContainer>
<Text>Hello World</Text>
</React.Fragment>
);
};
export default Routes;
Home.js:
import "react-native-gesture-handler";
import { StatusBar } from "expo-status-bar";
import React from "react";
import { StyleSheet, Text, View, Image } from "react-native";
import { APP_NAME, APP_VERSION, ENVIRONMENT, PRIMARY_COLOR } from "../env.json";
const Home = () => {
return (
<View style={styles.home}>
<Image
source={require("../assets/android-chrome-192x192-transparent.png")}
style={styles.logo}
/>
<Text h1 style={styles.title}>
{APP_NAME}
</Text>
{ENVIRONMENT !== "Production" ? (
<>
<Text h5 style={styles.version}>
Version {APP_VERSION}
</Text>
<Text h6 style={styles.environment}>
Environment: {ENVIRONMENT}
</Text>
</>
) : (
""
)}
<StatusBar style="auto" />
</View>
);
};
const styles = StyleSheet.create({
title: {
color: PRIMARY_COLOR,
fontSize: 30,
fontWeight: "bold",
},
logo: {
width: 150,
height: 150,
tintColor: PRIMARY_COLOR,
},
version: {
color: PRIMARY_COLOR,
fontSize: 16,
},
environment: {
color: PRIMARY_COLOR,
fontSize: 12,
},
});
export default Home;
Login.js:
import "react-native-gesture-handler";
import { StatusBar } from "expo-status-bar";
import * as React from "react";
import { StyleSheet, TextInput, View, Button } from "react-native";
import { API_URL } from "../env.json";
const Login = () => {
const [text, onChangeUsername] = React.useState("");
const [password, onChangePassword] = React.useState("");
return (
<View style={styles.login}>
<Text h1>Login</Text>
<Text h2>Username</Text>
<TextInput
style={styles.input}
onChangeUsername={onChangeUsername}
placeholder="Username"
value={text}
/>
<Text h2>Password</Text>
<TextInput
style={styles.input}
onChangePassword={onChangePassword}
placeholder="Password"
value={password}
secureTextEntry={true}
/>
<Button title="Login" />
<StatusBar style="auto" />
</View>
);
};
const styles = StyleSheet.create({
login: {
flex: 1,
backgroundColor: "#fff",
alignItems: "center",
},
input: {
height: 40,
margin: 12,
borderWidth: 1,
},
});
export default Login;
This is what I'm seeing on the Android emulator:
I'm looking to have a navigation menu available to the user and also to have the Home page be the default landing page for the application. How do I do this? What am I doing wrong?
Your Home component must have {flex: 1} on it's container. Specifically in your case you've got 'styles.home' but you don't have that value included in your stylesheet.
And remove the {flex: 1} from the navigator.

react-navigation from 1.x to 5, how to migrate redux actions

App has all old code which I am upgrading to latest versions. It was using Redux for state management with StackNavigator. Since that is not supported, I am not able to understand how to migrate my existing redux actions, which were changing screens on various events.
An example action:
export const goToHome = () => ({
type: PUSH,
routeName: 'projectList',
});
Which earlier reached navReducer, which handled POPing and PUSHing of screens.
export default (state = initialState, action) => {
let nextState;
switch (action.type) {
case NAV_POP:
nextState = AppNavigator.router.getStateForAction(
NavigationActions.goBack(),
state
);
break;
...
Please suggest.
Thanks.
The navigationRef is used for the scenarios like this.
You can refer the documentation here
It states
Sometimes you need to trigger a navigation action from places where
you do not have access to the navigation prop, such as a Redux
middleware. For such cases, you can dispatch navigation actions from
the navigation container
Which exactly is your requirement, here we create a navigationref and use call the navigation methods from there.
The below is the code for a simple example, you can use the 'navigate' inside your reducer. Also you will have to move it to a separate file just like they've provided in the documetation.
import * as React from 'react';
import { View, Button, Text } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
const navigationRef = React.createRef();
function navigate(name, params) {
navigationRef.current && navigationRef.current.navigate(name, params);
}
function Home() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Button
title="Go to Settings"
onPress={() => navigate('Settings', { userName: 'Lucy' })}
/>
</View>
);
}
function Settings({ route }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Hello {route.params.userName}</Text>
<Button title="Go to Home" onPress={() => navigate('Home')} />
</View>
);
}
const RootStack = createStackNavigator();
export default function App() {
return (
<NavigationContainer ref={navigationRef}>
<RootStack.Navigator>
<RootStack.Screen name="Home" component={Home} />
<RootStack.Screen name="Settings" component={Settings} />
</RootStack.Navigator>
</NavigationContainer>
);
}
you can navigate through navigation container ref
you can call navigation().navigate("Settings") or navigation().goBack() in reducer
here is the demo of export navigation: https://snack.expo.io/#nomi9995/2eb7fd
App.js
import React,{useEffect} from 'react';
import { StyleSheet, Text, View } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
const navRef = React.createRef();
export const navigation=()=>{
return navRef.current && navRef.current
}
const TestComponent=()=> {
useEffect(()=>{
setTimeout(() => {
navigation().navigate("Settings")
setTimeout(() => {
navigation().goBack()
}, 3000);
}, 100);
})
return (
<View style={styles.container}>
<Text>TestComponent 1</Text>
</View>
);
}
const TestComponent2=()=> {
return (
<View style={styles.container}>
<Text>TestComponent 2</Text>
</View>
);
}
const RootStack = createStackNavigator();
export default function App() {
return (
<NavigationContainer ref={navRef}>
<RootStack.Navigator>
<RootStack.Screen name="Home" component={TestComponent} />
<RootStack.Screen name="Settings" component={TestComponent2} />
</RootStack.Navigator>
</NavigationContainer>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
reducder.js
import { navigation } from 'path of App.js';
export default (state = initialState, action) => {
let nextState;
switch (action.type) {
case NAV_POP:
nextState = navigation().goBack()
break;

Categories

Resources