How can I change text color of dropdown after switching to/from dark mode. The change is happening after restarting the application - react-native

I want the text color of the dropdown to change just after switching to/from dark mode. My code is changing the color of the text by switching to/from dark mode but for that, I have to restart the application. I want this to happen without restarting the application.
import React, { useState, useRef, useEffect } from 'react'
import { Picker } from '#react-native-picker/picker'
import { CgView } from './CgView'
import { CgText } from './CgText'
import Colors from '../Theme/Colors'
import { Appearance } from 'react-native'
const colorScheme = Appearance.getColorScheme();
const MonthtPicker = props => {
const { selectedMonth, onMonthChange } = props
const monthRef = useRef()
const dayRef = useRef()
const [textColor, setTextColor] = useState(Colors.commonTextColor)
useEffect(()=> {
const changeMode = () =>{
if (colorScheme === 'dark') {
// Use dark color scheme
setTextColor('white')
}
else{
setTextColor(Colors.commonTextColor)
}
}
changeMode()
}, [colorScheme])
return (
<CgView>
<CgText bdayLabel>Birthday</CgText>
<CgView row>
<CgView pickerContainer>
<Picker
ref={monthRef}
selectedValue={selectedMonth}
onValueChange={onMonthChange}
dropdownIconColor={Colors.commonTextColor}
itemStyle={{ color: Colors.commonTextColor }}
style={{ color: Colors.commonTextColor }}>
<Picker.Item
label='Select month'
value=' '
color={textColor}
/>
<Picker.Item
label='January'
value='January'
color={textColor}
/>
<Picker.Item
label='February'
value='February'
color={textColor}
/>
<Picker.Item
label='March'
value='March'
color={textColor}
/>
</Picker>
</CgView>
}
export default MonthPicker
Please explain me why my code is not working as expected and try to provide solution using useEffect.
Thank you in advance.

Related

React Native Application crashing on release but working on debug when trying to render a 3d .glb model using React Three Fiber

I have a bare react native app with expo-modules for expo-gl and react-three/fiber and react-three/drei. I'm trying to render a 3d .glb model with animations and external textures in a separate .jpg file and it is all working fine on debug but on release build the application crashes as soon as the application opens.
FATAL EXCEPTION: mqt_native_modules com.facebook.react.common.JavascriptException: Error: Could not load 36: undefined)
This is the error that i'm getting in adb logcat
github repo
Here is the code in app.js:
import React, { Suspense, useEffect, useRef, useState } from 'react'
import {View, Text, Button} from 'react-native';
import { useFrame, Canvas, useLoader, useThree, extend } from '#react-three/fiber/native'
import { useGLTF, Environment, useAnimations, useTexture } from '#react-three/drei/native'
import iphoneModelPath from './assets/iphone.glb'
import stacy from './assets/stacy.glb';
import stacyTex from './assets/stacy.jpg';
// import {Ipgone} from './Iphone.js';
// import * as THREE from 'three';
import useControls from 'r3f-native-orbitcontrols'
function StacyModel({url, url1}, props) {
const { nodes, animations } = useGLTF(url)
const texture = useTexture(url1)
const { ref, actions, names } = useAnimations(animations)
const [hovered, setHovered] = useState(false)
const [index, setIndex] = useState(3)
useFrame((state, delta) =>{
actions[names[index]].play();
})
return (
<group onClick={(event) => setIndex((index + 1) % names.length)} ref={ref} {...props} dispose={null}>
<group rotation={[Math.PI / 2, 0, 0]} position={[0,-4,0]} scale={0.04}>
<primitive object={nodes.mixamorigHips} />
<skinnedMesh
geometry={nodes.stacy.geometry}
skeleton={nodes.stacy.skeleton}
rotation={[-Math.PI / 2, 0, 0]}
scale={100}>
<meshStandardMaterial map={texture} map-flipY={false} skinning />
</skinnedMesh>
</group>
</group>
)
}
// useGLTF.preload(iphoneModelPath)
export default function App() {
const[OrbitControls, events] = useControls();
return (
<View style={{flex: 1}} {...events}>
<Canvas gl={{ physicallyCorrectLights: true }} camera={{ position: [0, 0, 16], fov: 50 }}
onCreated={(state) => {
const _gl = state.gl.getContext()
const pixelStorei = _gl.pixelStorei.bind(_gl)
_gl.pixelStorei = function(...args) {
const [parameter] = args
switch(parameter) {
case _gl.UNPACK_FLIP_Y_WEBGL:
return pixelStorei(...args)
}
}
}}
>
<color attach="background" args={[0x000000]} />
<directionalLight intensity={0.8} position={[-6, 2, 2]}/>
<Suspense>
<Environment preset="park" />
<StacyModel url={stacy} url1={stacyTex} />
</Suspense>
<OrbitControls />
</Canvas>
{/* </OrbitControlsView> */}
</View>
)
}
You can view the build.gradle files from the repo.
Any help would be appreciated. Thanks!
I tried bundling the assets, minifying-js: false in build.gradle but nothing supposes to work. If any one can provide further info on what is happening and how it can be solved. it will be highly appreciated.

How to press a next button and focus another text field input?

Version react hook form
^7.27.0
What I tried to follow and without successful
react hook form - Discussions 7818
react hook form - Issues 230
About what I have
I have 4 text field components at my screen, the name of each text field is name, documentation, email, password and I would like to know how can I setup some configuration that it will be pressed the NEXT button at keyboard and will focus the following text fields?
An example that I have inside at my component file, again I would like to press the next button and the next component that I will config, will be focus.
<TextField
name="name"
label={I18n.t('registerPersonal.fullNameLabel')}
placeholder={I18n.t('registerPersonal.fullNameInput')}
icon={<TypographyIcon fill={!!errors.name && theme.colors.attention} />}
error={errors.name?.message}
errors={errors}
control={control}
returnKeyType="next"
/>
<TextField
name="documentation"
label={I18n.t('registerPersonal.documentIdentificationLabel')}
placeholder={I18n.t('registerPersonal.documentIdentificationInput')}
icon={
<DocumentIcon
fill={!!errors.documentation && theme.colors.attention}
/>
}
error={errors.documentation?.message}
control={control}
returnKeyType="next"
/>
Some properties that I get at my personal hook
const {
control,
handleSubmit,
formState: { errors, isValid }
} = useForm({ resolver: yupResolver(schema) })
My component TextField
import { TextInputProps, Text } from 'react-native'
import { Control, useController } from 'react-hook-form'
import { Container, Wrapper, TextInput, Label } from './styles'
import theme from '../../global/styles/theme'
type TextFieldProps = {
placeholder?: string
label?: string
icon?: React.ReactNode
error?: string
errors?: {
[x: string]: any
}
name: string
control: Control
} & TextInputProps
export function TextField(props: TextFieldProps) {
const { placeholder, label, icon, error, errors, name, control, ...rest } =
props
const { field } = useController({
control,
defaultValue: '',
name
})
return (
<>
<Container>
{!!label && <Label>{label}</Label>}
<Wrapper hasLabel={!!label} hasError={!!error}>
{!!icon && icon}
<TextInput
value={field.value}
onChangeText={field.onChange}
placeholder={error ? error : placeholder}
placeholderTextColor={
error ? theme.colors.attention : theme.colors.grayColor
}
{...rest}
/>
</Wrapper>
{errors && errors.name && errors.name.type === 'matches' && (
<Text>{errors.name.message}</Text>
)}
</Container>
</>
)
}
your component must include ref prop like
<TextInput
ref={inputRef} // this one
value={field.value}
onChangeText={field.onChange}
placeholder={error ? error : placeholder}
placeholderTextColor={
error ? theme.colors.attention : theme.colors.grayColor
}
{...rest}
/>
then, you need to create ref from parent for each field
const emailRef = useRef(null);
const passwordRef = useRef(null);
after this, you need to add the props that is
onSubmitEditing={() => passwordRef.current.focus()} // to auto focus password field
finally,
<TextField
onSubmitEditing={() => passwordRef.current.focus()} // here
name="name"
label={I18n.t('registerPersonal.fullNameLabel')}
placeholder={I18n.t('registerPersonal.fullNameInput')}
icon={<TypographyIcon fill={!!errors.name && theme.colors.attention} />}
error={errors.name?.message}
errors={errors}
control={control}
returnKeyType="next"
/>

TooltipHost callout is not closed when mouse gets out of content

I have the TooltipHost component listed below. After callout is shown, if I move the mouse to gapspace, e.g. to the area between button and callout, callout stays visible.
I want the callout to be closed when mouse gets out of button, even if it is inside the gapspace.
import * as React from "react";
import {
TooltipHost,
DefaultButton,
DirectionalHint
} from "office-ui-fabric-react";
export const ButtonWithTooltip: React.FC<any> = () => {
return (
<>
<TooltipHost
content="tooltip content"
calloutProps={{
gapSpace: 60,
calloutMaxWidth: 150,
isBeakVisible: false,
directionalHint: DirectionalHint.bottomLeftEdge
}}
>
<DefaultButton styles={{ root: { width: "100%" } }} allowDisabledFocus>
Submit
</DefaultButton>
</TooltipHost>
</>
);
};
This appears to be expected behavior since the tooltip is getting closed once the mouse leaves tooltip container
To control TooltipHost component visibility the following methods could be utilized:
ITooltipHost.show - Shows the tooltip
ITooltipHost.dismiss - Dismisses the tooltip
The following example demonstrates how to hide a tooltip once mouse leaves a button
import {
DefaultButton,
DirectionalHint,
ITooltipHost,
TooltipHost
} from "office-ui-fabric-react";
import * as React from "react";
import { useRef } from "react";
const ButtonWithTooltip: React.FC<any> = () => {
const tooltipRef = useRef<ITooltipHost>(null);
function handleMouseLeave(e: any): void {
if (tooltipRef.current) {
tooltipRef.current.dismiss();
}
}
return (
<>
<TooltipHost
componentRef={tooltipRef}
content="tooltip content"
calloutProps={{
gapSpace: 90,
calloutMaxWidth: 150,
isBeakVisible: true,
directionalHint: DirectionalHint.bottomLeftEdge
}}
>
<DefaultButton
onMouseLeave={handleMouseLeave}
styles={{ root: { width: "100%" } }}
allowDisabledFocus={true}
>
Submit
</DefaultButton>
</TooltipHost>
</>
);
};
Demo

How to use External web page in React Native View

I want to use external web page in my React Native App . I have button on my app and want to open external web page onPress button in my app not on browser.
I have tried WEBVIEW but not helped me.
now I have Tried this :
<HTMLView
value={this.props.html}
onLinkPress={(url) => alert('clicked link: ', url)}
/>
how can i do this ?
I have tried this and its working for me.
install react-native-custom-tabs using this command
npm install react-native-custom-tabs --save
and than link custom tabs package using
react-native link react-native-custom-tabs
and than call it
import {CustomTabs,ANIMATIONS_SLIDE,ANIMATIONS_FADE} from 'react-native-custom-tabs';
openCustomizedCustomTabs() {
this.openGoogle({
toolbarColor: '#607D8B',
enableUrlBarHiding: true,
showPageTitle: true,
enableDefaultShare: true,
animations: ANIMATIONS_SLIDE
});
}
errorOccur() {
this.openGoogle({
//toolbarColor: '607D8B', // <--- Invalid toolbar color.
enableUrlBarHiding: '#607D8B', // <-- Type Error.
})
}
openGoogle(option) {
CustomTabs.openURL('https://www.google.com', option).then((launched: boolean) => {
console.log(`Launched custom tabs: ${launched}`);
}).catch(err => {
console.error(err)
});
}
render(){
return <Button marginTop={10} onPress={() => this.openCustomizedCustomTabs()}>
Custom Tab
</Button>
}
and run app.
function renderNode(node, index, siblings, parent, defaultRenderer) {
if (node.name == 'iframe') {
const a = node.attribs;
const iframeHtml = `<iframe src="${a.src}"></iframe>`;
return (
<View key={index} style={{width: Number(a.width), height: Number(a.height)}}>
<WebView source={{html: iframeHtml}} />
</View>
);
}
}
class Page extends React.Component {
render() {
const htmlContent = `
<div>
<iframe src={this.props.utl} width="360" height="300" />
</div>
return (
<HTMLView value={htmlContent} renderNode={renderNode} />
);
}
}
then use it like:
<Page url="the url here..." />
React Native WebView Component has been Added in new Release to Documentation .
https://facebook.github.io/react-native/docs/webview.html
import React, { Component } from 'react';
import { WebView } from 'react-native';
class MyWeb extends Component {
render() {
return (
<WebView
source={{uri: 'https://github.com/facebook/react-native'}}
style={{marginTop: 20}}
/>
);
}
}

How to correctly large state updates in React Native?

I am writing a small ReactNative application that allows users to invite people to events.
The design includes a list of invitees, each of which is accompanied by a checkbox used to invite/uninvite said invitee. Another checkbox at the top of the list that performs a mass invite/uninvite on all invitees simultaneously. Finally a button will eventually be used to send out the invites.
Because the state of each of these elements depends changes made by the other I often need to re-render my entire UI whenever the user takes action on one of them. But while this works correctly it is causing me quite a few performance issues, as shown in this video
Here's the code I'm using:
import React, { Component } from 'react';
import { Container, Header, Title,
Content, Footer, FooterTab,
Button, Left, Right,
Center, Body, Text, Spinner, Toast, Root , CheckBox, ListItem, Thumbnail} from 'native-base';
import { FlatList, View } from 'react-native';
export default class EventInviteComponent extends Component {
constructor(props) {
super(props);
console.disableYellowBox = true;
this.state = {
eventName: "Cool Outing!",
invitees:[]
}
for(i = 0; i < 50; i++){
this.state.invitees[i] = {
name: "Peter the " + i + "th",
isSelected: false,
thumbnailUrl: 'https://is1-ssl.mzstatic.com/image/thumb/Purple111/v4/62/08/7e/62087ed8-5016-3ed0-ca33-50d33a5d8497/source/512x512bb.jpg'
}
}
this.toggelSelectAll = this.toggelSelectAll.bind(this)
}
toggelSelectAll(){
let invitees = [...this.state.invitees].slice();
let shouldInviteAll = invitees.filter(invitee => !invitee.isSelected).length != 0
let newState = this.state;
newState = invitees.map(function(invitee){
invitee.isSelected = shouldInviteAll;
return invitee;
});
this.setState(newState);
}
render() {
let invitees = [...this.state.invitees];
return (
<Root>
<Container>
<Content>
<Text>{this.state.eventName}</Text>
<View style={{flexDirection: 'row', height: 50, marginLeft:10, marginTop:20}}>
<CheckBox
checked={this.state.invitees.filter(invitee => !invitee.isSelected).length == 0}
onPress={this.toggelSelectAll}/>
<Text style={{marginLeft:30 }}>Select/deselect all</Text>
</View>
<FlatList
keyExtractor={(invitee, index) => invitee.name}
data={invitees}
renderItem={(item)=>
<ListItem avatar style={{paddingTop: 20}}>
<Left>
<Thumbnail source={{ uri: item.item.thumbnailUrl}} />
</Left>
<Body>
<Text>{item.item.name}</Text>
<Text note> </Text>
</Body>
<Right>
<CheckBox
checked={item.item.isSelected}/>
</Right>
</ListItem>}/>
</Content>
<Footer>
<FooterTab>
<Button full
active={invitees.filter(invitee => invitee.isSelected).length > 0}>
<Text>Invite!</Text>
</Button>
</FooterTab>
</Footer>
</Container>
</Root>);
}
}
In your code, in class method toggelSelectAll() {...} you modify the state directly by using this.state = ..., which is something to be avoided. Only use this.state = ... in your class constructor() {...} to initialize the state, and you should only use this.setState({...}) to update the state anywhere else.
Not sure if this should help your performance issues, but try replacing toggelSelectAll() with the following:
toggelSelectAll() {
const {invitees} = this.state;
const areAllSelectedAlready = invitees.filter(({isSelected}) => !isSelected).length === 0;
this.setState({
invitees: invitees.map(invitee => ({
...invitee,
isSelected: !areAllSelectedAlready
}))
});
}
Good luck! And, let me know if you would like me to refactor your above code to remove the 2nd this.state = ... in your constructor (which, once again, should be avoided when writing React).
I suggest:
Dividing your code by creating multiple components, so you won't have a massive render()
Using Redux to store invitee / global state, so you can choose which components should re-render in case of modifications
That's a good way to learn React Native!