UI Kitten Theme Switch Causes Flicker - react-native

I am building an app with UI kitten and Expo. I am facing a very strange issue with switching theme. On any kind of onPress() event it works perfectly fine but as soon as I use Toggle() from UI kitten and try switching theme with onChange() the theme flickers between light and dark twice before switching to required theme. Here is my code:
const [darkMode, setDarkMode] = React.useState();
const toggleTheme = () => {
themeContext.toggleTheme();
setDarkMode(!darkMode);
}
return (
<View>
{/* Some Code */}
<Toggle checked={darkMode} disabled={loading} status='basic' onChange={toggleTheme} checkedIcon={checkIcon}/>
{/* Some More Code */}
</View>
)
I can't understand what could possibly be wrong here. There are no re-renders that might cause this behavior. While the buttons are working accurately, the toggles show this behavior.

Related

React native touchable opacity always active

I am using touchable opacity for my home page button, all menus are working perfectly but are not working correctly in two scenarios.
While launching the share popup and moving to another application
Open the play store for rating.
The problem I am facing
While pressing the button, the opacity and all actions work properly, but after coming back to the application, still, the touchable opacity is active.
<TouchableOpacity onPress={()=> shareApp() }>
<View>
<Image source={require('../Assets/Home_page/share.png')}/>
</View>
<View>
<Text>Share my app</Text>
</View>
</TouchableOpacity>
shareApp = () => {
var link="https://play.google.com/store/apps/details?id="+_packageid;
const result = await Share.share({
title: 'App link',
message:'Best app \n'+link,
url:link
});
}
See the above image, after returning to the application, still, the opacity is active. The same happened if the following code is executed.
Linking.openURL(link)

Touchable view and activating another components animation

New to react native and in a component, I have a list of views that include a checkbox (react-native-bouncy-checkbox). Each view is wrapped in a TouchableWithoutFeedback(So I can click the entire view, not just the checkbox) and I have a boolean useState to tell the checkbox whether to display the check or not.
The issue I'm at is that I chose the library for the checkbox because the animation when it's clicked looks very nice. However, the animation doesn't play if I hit the view ~ only if I hit the actual checkbox, which is rather small in my app.
Is there any way to tell another component that it needs to act like it was pressed, so it can play its animation?
Code for clarity:
const Task = ({ id, text }: Types) => {
const [checked, setChecked] = React.useState(false);
return (
<TouchableWithoutFeedback onPress={() => setChecked(!checked)}>
<View style={styles.container} >
<BouncyCheckbox
disableBuiltInState={true}
isChecked={checked}
fillColor="blue"
iconStyle={{ borderColor: 'gray' }}
/>
<Text>{text}</Text>
</View>
</TouchableWithoutFeedback>
)
};
Okay figured it out. Apparently React native allows you to create refs to other components and you can use the reference.onPress() to activate the animation.

How to change default background colour in React Native

I recently updated from RN 0.60 to 0.65, and after hours of debugging I can get my app to build and run again. However, for some reason the background colour of my app has changed from white to gray.
I'm using react-native-router-flux for navigation, but either the styling is broken in the latest react-native release, or I'm missing something obvious.
Here's how it has always been set up:
const RouterComponent = () => {
const sceneConfig = {
cardStyle: {
backgroundColor: 'white',
},
};
return (
<Router {...sceneConfig}/>
[...]
</Router>
This no longer does anything. Here's what else I've tried:
Directly adding style properties to <Router> using sceneStyle, as recommended in the docs
Directly adding style properties to each individual scene by using style property
Neither of these approaches work, and I'm now stuck with an app that has a gray background (#f2f2f2) on every screen. I'm not even sure if this is an issue with react-native-router-flux but it definitely seems like the most likely cause.
Digging through the issues on the Github repo, I found one person flagging that this could be an incompatibility with react-native-screens, which seems to have been added to my project as a result of the upgrade to RN 0.65. This is a shot in the dark, as I'm not even sure what that library is used for.
Has anyone managed to change the background colour of their app on RN 0.65 and react-native-router-flux v4.3.0?
Edit:
Here's an example of how I tried to style individual scenes, which didn't work:
<Scene
title={'Profile'}
renderTitle={() => <View />}
// Neither of the below options has any effect
sceneStyle={{backgroundColor: 'red'}}
style={{backgroundColor: 'red'}}
key="profile"
hideNavBar
icon={TabIcon}
iconName="account-circle-outline"
back={false}
component={Profile}
/>
I suggest you create a wrapper component and wrap your pages on it to easily manage the specification.
this is the way I use it in my applications:
const MainView = ({children}) => {
return (
<View style={styles.container}>{children}</View>
)
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#ff0",
},
});
Now, use this component in other screens, for example in the HomeScreen:
const HomeScreen = () => {
// rest of the codes ...
return (
<MainView>
// rest of the codes ...
</MainView>
)
}
You can even pass the container style through props to the MainView instead of creating the style on it. in this way, you can pass different styles in different screens.

'elevation'/'zIndex' prop on React Native View not working on Android

I'm trying to add a hit slop to some icons and I want them to persist even if the icon is hidden under another component.
This is already working fine on iOS with the zIndex prop, but neither the zIndex or elevation prop seem to be having any effect on Android. The icon is still clickable, just without the hit slop surrounding it. This is likely not an issue with the hit slop, as it works fine on a screen alone when not inside of a component.
export const RemoveIndicator = ({ icon, onPress }) => (
<View
style={ {
elevation: 2,
zIndex: 99,
} }
>
<TouchableIcon
color={ colors.Red500 }
name={ icon || 'Circle_Remove_Solid' }
onPress={ onPress }
size={ 16 }
/>
</View>
);
The TouchableIcon component is a component that contains a glyph (given the color, name, and size), wrapped in a TouchableOpacity that takes an onPress function. The hit slop is calculated inside the TouchableIcon based on the size prop.
I expect the icon to be clickable in an area around it, but it is only clickable on the visible glyph itself.

How to hide the statusBar when react-native modal shown?

I want to hide the status bar, when modal window is shown.
My setup is as following, but it won't work as expected:
<StatusBar animated={true} hidden={true} translucent={true}>
Use statusBarTranslucent
If your status bar is translucent, you can set statusBarTranslucent to the modal.
Added since React Native 0.62
<Modal {...props} statusBarTranslucent>...</Modal>
Credit: https://github.com/react-native-modal/react-native-modal/issues/50#issuecomment-607535322
This is a known issue and there seems to be no official/React way to fix it yet. You can follow the discussion here:
https://github.com/facebook/react-native/issues/7474
I saw a post in this discussion which proposes a hack to hide it, but I haven't tried it on my project. You can also upvote this trick if it works for you.
<View style={styles.outerContainer}
<View style={styles.container}>
<StatusBar hidden={true}/>
<View style={styles.content}>
</View>
<Modal animation={fade} transparent={true}>
{/*Modal Contents Here*/}
</Modal>
</View>
A more solid fix may be changing the theme of activity in native android code.
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.ReactNative.AppCompat.Light.NoActionBar.FullScreen">
<!-- Customize your theme here. -->
</style>
<style name="AppTheme.Launcher">
<item name="android:windowBackground">#drawable/launch_screen</item>
</style>
</resources>
Credits go to Traviskn and mbashiq who proposed fixes above. I recommend you to subscribe that issue.
According to the documentations, you should be able to hide status bar in both iOS and Android using this
import {StatusBar} from 'react-native';
StatusBar.setHidden(true);
We can use the background of StatusBar to solve this problem easily but may not the best.
<Modal transparent>
{Platform.OS === 'android' ?
<StatusBar backgroundColor="rgba(0,0,0,0.5)"/>
: null
}
<View style={{backgroundColor: 'rgba(0,0,0,0.5)'}}>
// ModalContent here
</View>
</Modal>
Just use the same background and this problem can be solved.
I am actually facing the same issue for some time, I tried many solutions but I didn't get rid of this problem. I also tried to use native Android code to hide the StatusBar for a single component it works in other component but when I use it in modal it just not working. So, at last, I got a solution that works for me. I remove the modal view and replace it with react-navigation to navigate to a specific path and handle the back button using BackHandler component.
i achieve this creating a custom status bar component with a modal prop:
import React from 'react'
import { StatusBar } from 'react-native'
const MyStatusBar = (props) => {
const { backgroundColor } = props
const { barStyle } = props
const { translucent } = props
const { hidden } = props
const { showHideTransition } = props
const { modal } = props;
(modal !== undefined) ? StatusBar.setHidden(true) : StatusBar.setHidden(false)
return (
<StatusBar showHideTransition={showHideTransition} hidden={hidden} translucent={translucent} backgroundColor={backgroundColor} barStyle={barStyle} />
)
}
export default MyStatusBar
inside my base component modal prop is undefined so custom status bar is shown:
<MyStatusBar backgroundColor={theme.colors.primary} barStyle={'light-content'} />
and then calling inside the component who call the modal:
<MyStatusBar modal={modalVisible ? true : undefined} />
I think the root of my problem is the same, but it appeared a little different than how it is described above.
Expected behaviour: When the Modal becomes visible the StatusBar should hide.
const [showModal, setShowModal] = useState(false)
...
<Modal
visible={showModal}
>
<StatusBar hidden={showModal} />
...
Actual bahviour: Sometimes the StatusBardissapears as expected, other times just the StatusBar background color goes away and the actual StatusBar remains.
Workaround: Due to the flickering behaviour I think the problem is a racing condition of the native Android dialog. Therefore, I built a custom Modal component that uses the StatusBar imperative api to make sure the StatusBar hide call is made before the Modal appears. So far the Problem has not reappeared.
Here is the custom Modal component:
const Modal = ({ visible, children, ...rest }) => {
const [modalVisibility, setModalVisibility] = useState(false);
useEffect(() => {
if (visible) {
StatusBar.setHidden(true);
setModalVisibility(true);
} else {
StatusBar.setHidden(false);
setModalVisibility(false);
}
}, [visible]);
return (
<RNModal
visible={modalVisibility}
{...rest}
>
{children}
</RNModal>
);
};
export default Modal;
Hello you can try this
<View style={styles.outerContainer}
<View style={styles.container}>
<StatusBar hidden={true}/>
<View style={styles.content}>
</View>
<Modal animation={fade} transparent={true}>
{/* Contents Here*/}
</Modal>
</View>
<StatusBar backgroundColor={'transparent'} translucent={true} />