So basically I have a Screen in my app that has a Button in it and this button should open a Modal that is also a selfmade component in the same screen js file.
I am setting the state visible in the screen and the button has an onPress handler that toggles the visible state (false/true).
I dont know how to display my own modalComponent when the button is clicked.
btw using react-native-modal
Own modal component:
class PhasenModal extends Component {
render() {
return (
<View>
<Modal isVisible={this.props.visible}>
<View style={{ flex: 1 }}>
<Text>I am a modal</Text>
</View>
</Modal>
</View>
);
}
}
In my ScreenView :
<Button
buttonStyle={styles.phaseButton}
title="Choose"
onPress={() => this.phasenModalHandler()}
/>
The onPress fnct:
phasenModalHandler() {
this.setState({ visible: !this.state.visible });
if (this.state.visible) {
return <PhasenModal visible={this.state.visible} />;
} else {
return;
}
}
I expect the button to show the Modal but it doesnt show anything ,
the state gets toggled correctly tho it switched from false to true.
I guess my onPress fctn is wrong becaus I dont know how to render the component.
Thank you in advance.
What you return from your event handler will not be rendered, so you could instead use the visible value in your state to conditionally render the PhasenModal component.
class ScreenView extends Component {
state = {
visible: false
};
phasenModalHandler = () => {
this.setState(({ visible }) => ({ visible: !visible }));
};
render() {
return (
<>
<Button
buttonStyle={styles.phaseButton}
title="Choose"
onPress={this.phasenModalHandler}
/>
{this.state.visible && <PhasenModal />}
</>
);
}
}
class PhasenModal extends Component {
render() {
return (
<View>
<Modal isVisible>
<View style={{ flex: 1 }}>
<Text>I am a modal</Text>
</View>
</Modal>
</View>
);
}
}
Related
I am trying to show or print the duration (timer) when the button start is pressed, but nothing is showing after pressing start. I tried doing Button instead of TouchableOpacity, but still, nothing changed.
class Timer extends Component {
constructor(props){
super(props)
this.state = {
count: 0
}
}
render () {
const {count} = this.state
return (
<ScrollView>
<SafeAreaView style={styles.container}>
<View style={styles.textInputContainer}>
<Text style={styles.txtHello}>Press start when ready</Text>
<View style={styles.sep}>
</View>
<TouchableOpacity style={styles.button}
onPress={ () =>
<View style={styles.textInputContainer}>
<Text>
<h2> Duration: {count}</h2>
</Text>
</View>
}
>
<Text>start</Text>
</TouchableOpacity>
</View>
</SafeAreaView>
</ScrollView>
)
}
componentDidMount(){
this.myInterval = setInterval(()=>{
this.setState({
count: this.state.count + 1
})
}, 1000)
}
}
I don't think this is a right way to do it in React. What you would like to do is set a isVisible state, change it with your onPress props in Button/TouchableOpacity and finally conditionally show the view you want to display based on that isVisible variable. Something like this:
class Timer extends Component {
constructor(props){
super(props)
this.state = {
isVisisble:false;
}
}
render(){
return(
<View>
<TouchableOpacity
onPress={ () => this.setState((prevState)=>{isVisible:!prevState.isVisible})}
>
<Text>start</Text>
</TouchableOpacity>
{this.state.isVisible && <View></View>} <- Conditional View here
</View>
)}
I am using react-navigation version 3, I have bottom tab navigator, have 4 tabs.
out of which one is chat-screen, called as Chat, containing two views as:
main chat screen for chats or posts
if not login then show with buttons for signup and login.
when clicked on signup or login, it will take to respective screen for signing or logging in.
but from login/signin page when I click on bottom-tab navigator on Chat, it should again reload and check whether user is logged in or not?
problem is when I am navigating to signin/login page, from my tab, then It's not refreshing or called again or remounted.
my chat component is :
class ChatScreen extends React.Component {
constructor(props) {
super(props);
this.state = {
loading: true,
refreshing: false
}
this.onRefresh = this.onRefresh.bind(this);
let WebViewRef;
}
componentDidMount() {
this.didFocusListener = this.props.navigation.addListener(
'didFocus',
() => {
console.log('bottom tab navigator is called');
},
);
if (this.props.userInfo) {
this.get_access_token()
}
else {
console.log("! this.props.userInfo ")
}
}
render() {
if (this.props.userInfo && this.state.access_token)
return (
<SafeAreaView style={{ flex: 1 }}>
<ScrollView
contentContainerStyle={{ flex: 1 }}
refreshControl={<RefreshControl refreshing={this.state.refreshing} onRefresh={this.onRefresh} />}
>
<View style={{ flex: 1 }}>
<WebView
source={{ uri: 'my-demosite-anywebsite.com?access_token=' + this.state.access_token }}
onLoad={() => this.setState({ loading: false })}
ref={WebViewRef => (this.WebViewRef = WebViewRef)}
/>
</View>
</ScrollView>
</SafeAreaView>
)
else if (!this.props.userInfo) {
return <MyCompanyLogoScreen />
}
else {
return <LoadingScreen />
}
}
}
class MyCompanyLogoScreen extends React.Component{
render() {
return (
<View style={styles.container}>
{
!this.state.request_to_login ?
<View> <MyCompanyLogoScreenAllComponents/>
<Button
bgColor="#4cd137"
textColor="#FFFFFF"
secondary
rounded
style={{ alignSelf: 'stretch', marginTop: hp(5),
width: '35%', marginRight: wp(6) }}
caption={'LOGIN UP'}
onPress={() =>
this.navigateToLoginScreen(redirect_to_signup_or_login
= "login")
}
/>
</View>
}
my problem is how can I refresh whole component when I tap on tab at bottomTabNavigator as Chat ?
also didFocus is not working.
React navigation >= 6
React Native Tab Navigation has an option prop as unmountOnBlur. Set it to true and it will reload the tab screens every time you click on tabs.
<Tab.Screen
initialParams={{ ...params, article: null }}
options={{
title: "HomePage",
unmountOnBlur: true,
}}
name="HomePage"
component={ResenhaPage}
/>
you can use higher order component which passes the isFocused prop into a wrapped component. example:
import { withNavigationFocus } from 'react-navigation';
class TabLabel extends React.Component {
componentDidUpdate(prevProps) {
if (prevProps.isFocused !== this.props.isFocused) {
//Call any action to update you view
//fetch data when the component is focused
//To prevent extra component re-renders, you may need to write some logic in shouldComponentUpdate
}
}
render() {
return <Text>{this.props.isFocused ? 'Focused' : 'Not focused'}</Text>;
}
}
// withNavigationFocus returns a component that wraps TabLabel and passes
// in the navigation prop
export default withNavigationFocus(TabLabel);
Hey there so i'm new to react native and javascript and currently i'm learning to make a custom radio button with images it looks like this my custom radio button in this page user is going to pick one button from the list, and i want to make it when the page first render it will show one pressed button and user is only allowed to pick one button. Can anyone tell me how to figure this out? Thanks in advance
here are my codes
RadioButton.js
export default class RadioButton extends Component {
constructor(props) {
super(props);
this.state = {
selected: this.props.currentSelection === this.props.value,
}
}
button() {
var imgSource = this.state.selected? this.props.normalImg : this.props.selectedImg;
return (
<Image
source={ imgSource }
/>
);
}
render() {
let activeButton = this.props.activeStyle ? this.props.activeStyle : styles.activeButton;
return (
<View style={[styles.container, this.props.containerStyle, this.state.selected || this.props.normalImg ? activeButton : inactiveButton]}>
<TouchableOpacity onPress={() => {
this.setState({ selected: !this.state.selected });
}}>
{
this.button()
}
</TouchableOpacity>
</View>
);
}
}
ActivityLog.js
class ActivityLog extends Component {
constructor(props){
super(props);
}
render() {
return (
<View style={styles.innerContainer}>
<Text style={styles.dialogText}>{`Log my activity at ${time} as...`}</Text>
<View style={styles.buttonContainer}>
<RadioButton selectedImg={img.activity.breakA} normalImg={img.activity.break} containerStyle={{marginHorizontal: normalize(10)}}/>
<RadioButton selectedImg={img.activity.meetingA} normalImg={img.activity.meeting} containerStyle={{marginHorizontal: normalize(10)}}/>
</View>
<View style={styles.buttonContainer}>
<RadioButton selectedImg={img.activity.otwA} normalImg={img.activity.otw} containerStyle={{marginHorizontal: normalize(10)}}/>
<RadioButton selectedImg={img.activity.officeA} normalImg={img.activity.office} containerStyle={{marginHorizontal: normalize(10)}}/>
</View>
);
}
}
Extract the activeStatus to ActivityLog so as to track which button is selected,right now you are maintaing a state for every button as a local state.So it is difficult to know other components to know about the button's active status.
Here is a generic implementation for rough idea.
const Child=(props)=>{
<TouchableOpacity onPress={props.handlePress}>
<Text style={[baseStyle,active && activeStyle]}>{props.title}</Text>
</TouchableOpacity>
}
class Parent extends React.Component{
state={
selectedChild:''
}
changeSelection=(sometitle)=>{
this.setState({
selectedChild:sometitle
})
}
render(){
return(
<View>
<Child handlePress={()=>this.changeSelection('1')} active={this.state.selectedChild==='1'}/>
<Child handlePress={()=>this.changeSelection('2')} active={this.state.selectedChild==='2'}/>
<Child handlePress={()=>this.changeSelection('3')} active={this.state.selectedChild==='3'}/>
<Child handlePress={()=>this.changeSelection('4')} active={this.state.selectedChild==='4'}/>
</View>
)
}
}
Expo demo Link
I am unable to see my component for the "Log Out" aspect.
It is not entirely invisible, but instead of a block style just a single line is visible with no text.
However, The same reusable Button component works with the "Log In button".
renderContent() {
switch (this.state.loggedIn) {
case true:
return <Button> Log Out </Button>;
case false:
return <LoginForm />;
default:
return <Spinner size="large" />;
}
}
render() {
return (
<View>
<Header headerText="Authentication" />
{this.renderContent()}
</View>
);
when the user is not logged in the output is as follows:
the dark blue line below the Authentication header is the
However, The same Button with "Log In" works well.
I have tried to render a text component in place of the button component and it also works. Seems like just the Button in this particular conditional rendering is not working!
My Button component:
const Button = ({ onPress, children }) => {
const { buttonStyle, buttonTextStyle } = styles;
console.log({ children });
return (
<TouchableOpacity onPress={onPress} style={buttonStyle}>
<Text style={buttonTextStyle}>
{children}
</Text>
</TouchableOpacity>
);
};
the code block where Log In works:
renderButton() {
if (this.state.loading) {
return <Spinner size="small" />
}
return (
<Button onPress={this.onButtonPress.bind(this)}>
Log In
</Button>
);
}
I want to make a component where it renders a modal.
This component should have states{Key(integer),ImageLink(string),Visible(bool)}.
I am using flatlist. I want to render the component's modal on flatlist parent but component. States changes upon touch on flatlist child.
For example:
Modal Component which means to be single instance
import React from "react";
import {
View,
Modal,
Text,
StyleSheet,
TouchableHighlight,
Platform
} from "react-native";
export default class MySingleInstanceModal extend Component{
constructor(props) {
super(props);
this.state = {
Visiable: props.Visiable, \\Bool For turning Modal On or Off
ImageLink: props.ImageLink, \\String Image Online Link
Key: props.PostKey,\\integer Key
};
}
NextImage = (Current,Link )=> {
this.setState({ ImageLink: Link,Key:Current+1 });
};
ToggleMeOff = () => {
this.setState({ TurnMeOn: false });
};
ToggleMeOn = (MyKey,MyLink) => {
this.setState({ TurnMeOn: true,ImageLink: MyLink,Key:MyKey });
};
PrevImage = (Current,Link )=> {
this.setState({ ImageLink: Link,Key:Current-1 });
};
render() {
return (
<View>
<Modal
animationType="slide"
transparent={false}
visible={this.state.TurnMeOn}
>
<View style={{ marginTop: 22 }}>
<View>
<Text>Hello World!</Text>
<TouchableHighlight onPress={this.ToggleMeOff}>
<Text>Hide Modal</Text>
</TouchableHighlight>
<Image
source={{ uri: this.state.ImageLink }}
resizeMethod={"resize"}/>
</View>
</View>
</Modal>
</View>
);
}
}
Calling In Flatlist Parent:
render() {
return (
<View style={Style1.container}>
<MySingleInstanceModal/> // Here I want to call render
<FlatList
data={data}
initialNumToRender={4}
keyExtractor={this._keyExtractor}
renderItem={this._renderItem}
onEndReached={this._reachedEnd}
refreshing={isRefreshing}
onEndReachedThreshold={0.5}
onRefresh={this._refreshdata}
ListFooterComponent={this.renderFooter}
/>
</view>)
}
And want to change states of MySingleInstanceModal in flatlist items(flatlist child)
somewhere in the rendering of flatlist child item
render(){
return (
...
<TouchableHighlight onPress={() =>
MySingleInstanceModal.ToggleMeOn(this.state.Link,this.state.Key)}>
<Text>Open Modal For Me</Text>
</TouchableHighlight>
...
)
}
Which means component will render at parent but its states will be controlled by the child(Every flatlist item)