in my react-native application, there are two screens. I want to navigate from one screen to another such that if I press a button in the next screen, the first screen should be refreshed using a method doRefreshing() in the first screen.
Example:
const FirstScreen = (props) => {
const doRefreshing = () => {
...
};
return (
<View>
<TouchableOpacity
onPress={()=>props.navigation.navigate("secondScreen",doRefreshing())}
>
</TouchableOpacity>
</View>
);
}
The example code of second screen:
const SecondScreen = (props) => {
const doRefreshingInFirstScreen = () => {
/** What should I do here? */
};
return (
<View>
<Button
onPress={()=>doRefreshingInFirstScreen()}
>
</Button>
</View>
);
}
Can someone please tell me how shall I refresh the first screen when the button in second screen is pressed and call goes to doRefreshingInFirstScreen()? Or what else I can do to refresh the first screen upon clicking the button in the second screen? Will be really grateful for this help. Thanks in advance.
Did you mean this?
Snack
function HomeScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Screen</Text>
<Button
title="Go to Details"
onPress={() => navigation.navigate('Details', {onRefresh: () => console.log('refreshing...')})}
/>
</View>
);
}
function DetailsScreen(props) {
const { route } = props;
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Details Screen</Text>
<Button onPress={route.params.onRefresh} title="Refresh" />
</View>
);
}
React Native re-renders the screen whenever there is state change but this re-rendering will not happen if the screen is not being displayed. As for your scenario, I will suggest using redux to store the values that need to be refreshed from the second screen. Now whenever you go back to the first screen, then if you are reading value from the redux store, it will read the new values for all the variables that needed to be refreshed from the second screen, thus you will have the new values instead of the old ones.
Related
I'm writing a customised modal for prompts on my react native application. I'd want the modal to appear on click of an image. So, I added an onPress to the image to change a state value. When the state value is true, I'd want the modal to be displayed. The state successfully becomes true. However, I'd want it to switch back to false after the modal closes.
I tried changing the values from inside the component but it throws an error since I'm importing the component, and passing values as props. Below is what I have:
const [showPrompt, setShowPrompt] = useState(false)
const show =() => {
setShowPrompt(true);
setShowPrompt(false)
console.log(showPrompt)
}
<TouchableOpacity onPress={show}>
<Image source={{uri: imageSource}} style={{height:130, width:150}}/>
<Text style={{color:'white', textAlign:'center', fontSize:16, fontFamily:fonts.nunitoRegular}}>{title}</Text>
</TouchableOpacity>
{showPrompt && <CustomPrompt
open={modalVisible}
onClose={()=> setModalVisible(!modalVisible)}
openModalText={()=>setModalVisible(true)}
/>
}
try useCallback()
setShowPrompt(true);
//the time between these 2 operations is just a Boolean value assignment,
//that is, it is only a few milliseconds and you would be able to view
//the rendering
setShowPrompt(false);
import React, {useState, useCallback} from 'react'
const show = useCallback(() => {
setShowPrompt(!showPrompt);
console.log(showPrompt)
}, [showPrompt]);
<TouchableOpacity onPress={show}>
<Image source={{uri: imageSource}} style={{height:130, width:150}}/>
<Text
style={{
color:'white',
textAlign:'center',
fontSize:16,
fontFamily:fonts.nunitoRegular}}>
{title}
</Text>
</TouchableOpacity>
Now I have 3 screens in my simple App - firstScreen, secondScreen, thirdScreen.
In the firstScreen, there is a button - "Go back to previous screen!".
In the secondScreen and thirdScreen, there is a button - "Go to firstScreen".
When I navigate to firstScreen from second or third screen, how to know previous screen name?
I'd like to show alert in the firstScreen like this - "You are from secondScreen" or "You are from thirdScreen".
Is this possible?
One of the simplest ways I can think about is by passing parameters when navigating like it's described here.
function HomeScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Screen</Text>
<Button
title="Go to Details"
onPress={() => {
/* 1. Navigate to the Details route with params */
navigation.navigate('Details', {
itemId: 86,
fromScreen: 'screen 1',
});
}}
/>
</View>
);
}
Hope it helps!
I have a component within a StackNavigator that I always want to pass params to. This doesn't seem to work if my component is the first component loaded in a StackNavigator. Here's some code that illustrates the problem.
I start in component A.
I press the button to navigate to component B.
In the logs you can see that component B is loaded twice. The first time it's loaded without params.
Android SDK built for x86: rendering with: undefined
Android SDK built for x86: rendering with: ►{data:"from A"}
Also if you click the device back button it goes back to the screen with undefined params.
So there are two issues:
I only navigated once, but I have to go back twice to get back to where I was.
My component is loaded with no params even though I navigated with params.
Here's the code running in an expo snack: https://snack.expo.io/#bdzim/navigate-to-tab-from-parent
class A extends React.Component {
render() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Button
title="This is A. Press to go to B"
onPress={() => this.props.navigation.navigate(
'B', { data: 'from A' }
)}
/>
</View>
);
}
}
class B extends React.Component {
render() {
console.log('rendering with: ', this.props.navigation.state.params)
let params = JSON.stringify(this.props.navigation.state.params)
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>
params: {params}
</Text>
<Button
title="This is.. B! Press to go to A"
onPress={() => this.props.navigation.navigate('A')}
/>
</View>
);
}
}
const Stacks = StackNavigator({ B })
const Tabs = TabNavigator({ A, Stacks });
Let's suppose that i've a FlatList with some items, i press into one of them, then opens me another screen with the details of that item. Alright, so what i need is, after pressing the button called "Got it!" and goes into the back screen(FlatList screen), how can i set the background color to green in the row selected?
So i click in one item of the FlatList, then it shows me another screen with the details of that item
Once im in the Details screen, i press the button "Got it!", and it brings me back to the FlatList screen
This is exactly what i need, set a background color only in the View shown in that item, if i press another item and do the same thing, it will be shown changed the background both of them, and so on...
NOTE: class Details and ProfileActivity are inside App.js as a childs.
class ProfileActivity extends Component
{
GetFlatListItem (Description, Tutorial, Imagen, Title) {
Alert.alert(Description);
this.props.navigation.navigate('Fourth', {Tutorial, Imagen, Title});
}
return(
<View style = { styles.MainContainer }>
<Button title="Logout" onPress={ () => goBack(null) } />
<Text style = {styles.TextComponentStyle}> { this.props.navigation.state.params.Email } </Text>
<FlatList
data={ this.state.dataSource }
ItemSeparatorComponent = {this.FlatListItemSeparator}
renderItem={({item}) => <View style={{flex: 1, flexDirection: 'row'}}> <Text style={styles.points}>+ {item.points}</Text>
<Text style={styles.flatview} onPress={this.GetFlatListItem.bind
(this, item.description, item.tutorial, item.image, item.title)} >{item.title}</Text></View>}
keyExtractor={(item, index) => index.toString()}
/>
</View>
);
class Details extends Component{
onPress = () => {
this.setState({
const {goBack} =this.props.navigation;
})
}
return(
<View style = { styles.MainContainer }>
<TouchableHighlight
style={styles.buttonStyle}
onPress={this.onPress}
>
<Text> Got it! </Text>
</TouchableHighlight>
<Text style = {styles.TextComponentStyle}> { this.props.navigation.state.params.Title } </Text>
<Image
style={{width: 66, height: 58}}
source={{uri: this.props.navigation.state.params.Imagen}}
/>
<Text style = {styles.TextComponentStyle}> { this.props.navigation.state.params.Tutorial } </Text>
</View>
);
}
export default MainProject = createStackNavigator(
{
First: { screen: App },
Second: { screen: ProfileActivity },
Fourth: { screen: Details }
});
What i think is pass some values to the method onPress() in Details class, but i don't know which one exactly and how. Can somebody help me?
You will have to create this.state.someArrayName and copy from this.props.navigation.state.params and add backgroundColor key to each object and add your color. Apply that color to your items' view background color. *{{backgroundColor : item.backgroundColor}}
Create a function changeColor to change the color of backgroundColor
In your GetFlatListItem function, pass that function to detail view
On Detail View, call that changeColor function. this.props. changeColor() when you tap Got it button.
I'm using redux with react-navigation and would like to show the popup when the user clicks on the button on the react-navigation header-right button.
I wrapped the context menu at the root of my apps, as below
return (
<Provider store={store}>
<MenuContext style={{ flex: 1 }}>
<AppWithNavigationState />
</MenuContext>
</Provider>
)
in one of my screen, I have
static navigationOptions = {
headerTitle: 'News',
headerRight: (
<TouchableOpacity style={{ paddingLeft:15, paddingRight:15 }}>
<Icon name="more-vert" size={30} color="black" />
</TouchableOpacity>
),
}
When the user clicks on the right button, it should be like this
The menu items are dynamic, I will have to pull the data from one of my API and start rendering the menu data.
I've read through online it can be achieved using the context method, but I'm not sure how to implement it in my structure.
Could anyone advise me on this?
And is it possible to render it with my local variable?
The most custom way is to use Modal, when click the right button, called this.refs.modalRef.showModal(), which in your current page:
<View>
<PopupModal ref="modalRef" />
</View>
The PopupModal like this:
export default class PopupModal extends Component {
state = {
show: false,
}
showModal() {
this.setState({show: true});
}
closeModal = () => {
this.setState({show: false});
}
return (
<Modal
transparent
visible={this.state.show}
onRequestClose={this.closeModal}
>
<TouchableWithoutFeedback onPress={this.closeModal}>
<View style={{
width: '100%',
height: '100%',
opacity: 0.5,
backgroundColor: 'gray',
}} />
</TouchableWithoutFeedback>
<View></View> // your designed view, mostly position: 'absolute'
</Modal>
);
}
You can also pass some data to PopupModal by this.refs.modalRef.showModal(data), and in PopupModal:
showModal = (data) => {
this.setState({ data, show: true });
}
https://www.npmjs.com/package/react-native-material-menu
It works to me
headerRight:<View style={{marginRight:10}}>
<Menu
ref={this.setMenuRef}
button={<Text onPress={this.showMenu}><Icon style={{color:screenProps.headerTitleStyle.color,fontSize:25,marginRight:5}} name="md-more"/></Text>}
>
<MenuItem onPress={this.hideMenu}>Rate Us</MenuItem>
<MenuItem onPress={this.hideMenu}>Share App</MenuItem>
<MenuItem onPress={this.hideMenu}>Settings</MenuItem>
</Menu>
</View>,