I am beginner in using React Native.
I want to display the splash screen for my apps (for 1 second) and the navigate to different screen.
I have followed and combined some tutorial but I got an error.
My code is like this:
class SplashScreen extends React.Component {
static navigationOptions = {header: null,}
constructor(props){
super(props);
this.state = {
timePassed: false
};
}
render() {
let that = this;
setTimeout(function(){that.setState({timePassed: true})}, 1000);
const { navigate } = this.props.navigation;
if (!this.state.timePassed){
return (
<View style={styles.splashContainer}>
<Image source={require('./image/splash_screen.png')} style=
{styles.splash} />
</View>
);
}
else{
() => navigate('Login');
}
}
I got an error to navigate to new screen.
Can anyone help me? or is there any better solution?
Thank you.
Try this
class SplashScene extends Component {
function timeout(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function sleep(fn, ...args) {
await timeout(3000);
return fn(...args);
}
resetAndNavigate() {
const resetAction = NavigationActions.reset({
index: 0,
actions: [
NavigationActions.navigate({ routeName: 'Login'})
]
})
this.props.navigation.dispatch(resetAction)
}
componentDidMount() {
sleep.then(
this.resetAndNavigate()
)
}
}
Related
i'm new in react native. i want to add if condition in initialRouteName like code below. when "notification" variable is null move to "MemberProfile" page. but if "notification" variable is not null move to "ReviewMember" page. i try it code but still move to "MemberProfile" page. any solution?.
this is my code
var notification = null;
class DrawerMember extends Component {
constructor(props) {
super(props);
this.state = {
notifData: null
};
this.callCheck();
}
async callCheck() {
await AsyncStorage.getItem("#tryCode:notification", (err, result) => {
if (result != null) {
this.setState({
notifData: "testing data"
});
}
});
}
render() {
notification = this.state.notifData;
return <Root />;
}
}
const Root = createDrawerNavigator(
{
MemberProfile: {
screen: MemberProfileScreen
},
ReviewMember: {
screen: ReviewScreen
}
},
{
drawerPosition: "right",
initialRouteName: notification == null ? "MemberProfile" : "ReviewMember",
contentComponent: props => <SideBar {...props} />,
}
);
export default DrawerMember;
I think Root is created before the async function returns so notification is always null.
A possible way to solve this problem would be to use a SwitchNavigator as the first screen in your drawer. This navigator would be responsible for loading the notification and redirecting to the right screen.
Something along the lines of:
import React from 'react';
import { View, AsyncStorage, ActivityIndicator, StatusBar } from 'react-native';
export default class DummySwitch extends React.Component {
async componentDidMount() {
this.listener = this.props.navigation.addListener('willFocus', async () => {
const notification = await AsyncStorage.getItem('#tryCode:notification');
if (notification === null) {
this.props.navigation.navigate('MemberProfile');
}
else {
this.props.navigation.navigate('ReviewMember');
}
});
}
render() {
return (
<View>
<ActivityIndicator />
<StatusBar barStyle='default' />
</View>
);
}
}
As you can see, the switch screen just displays a loading button while accessing the async storage and deciding which route to take.
Then you define the drawer as usual but you add the switch screen as the initial route. You can also hide the label if you want by defining your own drawerLabel:
export default createDrawerNavigator({
Switch: {
screen: Switch,
navigationOptions: () => ({
drawerLabel: () => null,
}),
},
MemberProfile: {
screen: MemberProfileScreen,
},
ReviewMember: {
screen: ReviewScreen,
},
}, { initialRouteName: 'Switch' });
This is it, the drawer now selects the route based on your async storage.
I'm a a beginner in web development and I’m working on a video chat app built with create-react-app. I’m using recordRTC library for record and stream from users’s webcam and microphone.
When I stop recording, I also would like to close the webcam.
import React, { Component } from "react";
import RecordRTC from "recordrtc";
const captureUserMedia = callback => {
const params = { audio: true, video: true };
navigator.mediaDevices
.getUserMedia(params)
.then(callback)
.catch((error) => {
console.error(JSON.stringify(error));
});
};
export default class Recorder extends Component {
constructor(props) {
super(props);
this.recordVideo = null;
this.videoRef = React.createRef();
}
componentDidMount = () => {
captureUserMedia(stream => (this.videoRef.current.srcObject = stream));
};
startRecord = () => {
captureUserMedia(stream => {
this.recordVideo = RecordRTC(stream, { type: "video" });
this.recordVideo.startRecording();
});
};
stopRecord = () => {
this.recordVideo.stopRecording();
this.videoRef.current.srcObject.getTracks().forEach((track) => {
track.stop();
});
};
render() {
return (
<div>
<video ref={this.videoRef} autoPlay muted />
<div>
<button onClick={this.startRecord}>START</button>
<button onClick={this.stopRecord}>STOP</button>
</div>
</div>
);
}
}
I found here a related post where I found this:
stream.getTracks().forEach((track) => {
track.stop()
})
This stop the stream but the red circle is still present on the navigator tab (chrome) and the webcam's light is still lightning.
How can I do to turn off the webcam ?
The only way i found is to force a reload but I don't really wanna do this ...
If someone have an idea, please let me know.
Thanks for your reply :)
I found what I did wrong !
I called two times getUserMedia() method instead of one only (with captureUserMedia function).
You can try with the code below it will be ok !!!
...
componentDidMount = () => {
captureUserMedia((stream) => {
this.videoRef.current.srcObject = stream;
this.recordVideo = RecordRTC(stream, { type: "video" });
});
};
startRecord = () => {
this.recordVideo.startRecording();
};
stopRecord = () => {
this.recordVideo.stopRecording();
this.videoRef.current.srcObject.getTracks().forEach((track) => {
track.stop();
});
};
...
I'm working with React Native and React Navigation.
I have a component called App.js in which I declare the Drawer Navigation of React-Navigation.
In this I have an option to log out but I can not navigate to another component after removing the AsyncStorage
Does anyone know how to achieve it?
Thank you.
This is my code:
App.js
import { createDrawerNavigator, DrawerItems, NavigationActions } from 'react-navigation';
const customDrawerComponent = (props) => (
<SafeAreaView style={{ flex: 1 }}>
<ScrollView>
<DrawerItems
{...props}
/>
<TouchableOpacity style={styles.button} onPress={this.logOut} >
<Text> Logout </Text>
</TouchableOpacity>
</ScrollView>
</SafeAreaView>
);
logOut = () => {
// NOT WORKS
// this.props.navigation.navigate('Login')
//NOT WORKS:
this.myAction();
}
myAction = () => {
const nav = NavigationActions.navigate({
routeName: 'App',
});
return nav;
};
const AppDrawNavigator = createDrawerNavigator(
{
MainComponent: { screen: MainComponent,
navigationOptions: ({navigation}) => ({
drawerLockMode: 'locked-closed'
}) },
Login: { screen: LoginComponent,
navigationOptions: ({navigation}) => ({
drawerLockMode: 'locked-closed'
}) },
User: { screen: UsersComponent }
},
{
contentComponent: customDrawerComponent,
}
);
make this as a class like
export default class App extends React.Component {
constructor(props) {
super(props)
this.state = {
}
}
From your question I understand that either you want to :-
navigate from outside the components
navigate from components which do not have navigation prop.
For this I have tried 2 solutions and both work extremely fine though I based towards the second one.
First Solution
Use withNavigation from react-navigation package. If your components are deeply nested they wont have navigation prop unless u specify them manually or put them in context ;passing navigation prop becomes a real pain. So instead use withNavigation and your component would have navigation prop.
import {withNavigation} from "react-navigation";
const Component = ({navigation}) => {
const onPress = () => {
navigation.navigate(//ROUTE_NAME//)
}
return (
<TouchableOpacity onPress={onPress}>
<Text>Navigate</Text>
</TouchableOpacity>
)
}
export default withNavigation(Component);
Second Solution
Create a helper script and use that.
"use strict";
import React from "react";
import {NavigationActions} from "react-navigation";
let _container; // eslint-disable-line
export const navigation = {
mapProps: (SomeComponent) => {
return class extends React.Component {
static navigationOptions = SomeComponent.navigationOptions; // better use hoist-non-react-statics
render () {
const {navigation: {state: {params}}} = this.props;
return <SomeComponent {...params} {...this.props} />;
}
}
},
setContainer: (container) => {
_container = container;
},
reset: (routeName, params) => {
_container.dispatch(
NavigationActions.reset({
index: 0,
actions: [
NavigationActions.navigate({
type: "Navigation/NAVIGATE",
routeName,
params
})
]
})
);
},
goBack: () => {
_container.dispatch(NavigationActions.back());
},
navigate: (routeName, params) => {
_container.dispatch(
NavigationActions.navigate({
type: "Navigation/NAVIGATE",
routeName,
params
})
);
},
navigateDeep: (actions) => {
_container.dispatch(
actions.reduceRight(
(prevAction, action) =>
NavigationActions.navigate({
type: "Navigation/NAVIGATE",
routeName: action.routeName,
params: action.params,
action: prevAction
}),
undefined
)
);
},
getCurrentRoute: () => {
if (!_container || !_container.state.nav) {
return null;
}
return _container.state.nav.routes[_container.state.nav.index] || null;
}
};
In your parent component when you mount the navigation call following:-
"use strict";
import React from "react";
import App from "./routes";
import {navigation} from "utils";
class Setup extends React.Component {
render () {
return (
<App
ref={navigatorRef => {
navigation.setContainer(navigatorRef);
}}
/>
);
}
}
export default App;
Now, in your components you can directly use helpers from this script itself and navigation would be accessibly globally now.
import {navigate} from "utils/navigation";
For more details you can this thread
Your logout function is declared outside of the Navigator. This means you don't have access to the navigation prop there. However, your customDrawerComponent is a screen of your Navigator and it should have access to it.
So you can try something like this (props here are the props passed to the customDrawerComponent):
onPress={()=> {props.navigation.navigate("Login")}}
Plus your App.js seems kind of strange since you're not exporting any component. Have you pasted the whole code of App.js or just parts of it?
I have a button in header to open & close navigation drawer menu.
When I call below method from componentDidMount() it worked and opened the menu:
this.props.navigation.toggleDrawer();
But when I click the button it didn't work and just fade the screen!
Here is the component code :
export class Home extends BaseScreen {
constructor(props) {
super(props);
}
static navigationOptions = ({ navigation }) => {
const { params = {} } = navigation.state;
return ({
headerStyle: {
backgroundColor: '#FF9800'
}
, headerRight: <UserCoins />
, headerLeft: <Button onPress={params.handlePress} title='Menu' />
, title: 'title'
})
}
_handlePress() {
this.props.navigation.toggleDrawer();
}
state = {
coins: 0,
}
//
componentDidMount() {
this.props.navigation.setParams({
handlePress: this._handlePress.bind(this)
});
//here working
this.props.navigation.toggleDrawer();
}
render() {
return (<Text />);
}
}
export default Home
My navigator structure is :
1.SwitchNavigator
2.BottomTabNavigator
3.DrawerNavigator
4.StackNavigator (Home component inside it)
You can call 'navigation' that you are passing into your static NavigationOptions rather than trying to bind it in the params for navigation.
Try this on your onPress Event for your button
onPress={() => navigation.navigate('DrawerToggle')}
I am new in react-native world. I have two screen 1). Home 2). Notification
I am navigating from Home to Notification screen. When I am in Notification Screen that time when I press back button on that condition I want to refresh Home Screen. Please suggest.
Thanks in Advance!
Could you give us a little bit more details ? Are you using a navigator like react-navigation ?
If you want to trigger a method of the parent component from a child component, you should use props.
So, you can do something like this, if you are managing your view by yourself:
export default class Wrapper extends Component
{
state = {screen: 'Home'}
useNewScreen = screenToUse => this.setState({screen: screenToUse})
reloadHome = () => yourFunctionToRefreshThePage
render = () =>
{
if (this.state.screen === 'Home')
return (<Home goToNotif={() => this.useNewScreen('Notif')} />);
else if (this.state.screen === 'Notif')
return (<Notif onGoBack={() => this.reloadHome()} />);
}
}
class Home extends Component
{
render = () =>
{
return (
<TouchableOpacity onPress={() => this.props.goToNotif()}/>
);
}
}
class Notif extends Component
{
render = () =>
{
return (
<TouchableOpacity onPress={() => this.props.onGoBack()}/>
);
}
}
If you are using react-navigation, you can use the same idea:
You navigate to the new page with a special props
this.props.navigation.navigate('Notif', {
onGoBack: () => this.refresh()
});
And when you want to go back, you can call this method
this.props.navigation.state.params.onGoBack();
this.props.navigation.goBack(null);
I hope this is clear enough :)
Firstly always save navigated key screen to any TempStore.
Secondly set time interval to watch and compare both watching screen key and current screen key to able to call the inserted function from the screen you want to wacth and insert the screen mode to the function event..
OnScreen.js
import React, { Component } from 'react';
import { TempStore } from './helpers';
import {
Text,
View
} from "native-base";
class OnScreen extends Component {
constructor(props) {
super(props);
this.state = {
lastValue:'active'
}}
startWatching=()=>{
if (this.interval) { return; }
this.interval = setInterval(this.checkView, 100);
}
stopWatching=()=>{
this.interval = clearInterval(this.interval);
}
componentDidMount(){
this.startWatching();
}
componentWillUnmount(){
this.stopWatching();
}
checkView =()=> {
const proState = {};
proState.currentRoute=TempStore({type:'get',name:'_currentRoute'})
if(!proState.currentRoute){
proState.currentRoute={routeName:'Home',key:'Home'}
}
if(!this.props.statekey){return false}
var isVisible;
if(this.props.statekey === proState.currentRoute.key){
isVisible='active'
}else{
isVisible='inactive'
}
// notify the parent when the value changes
if (this.state.lastValue !== isVisible) {
this.setState({
lastValue: isVisible
})
this.props.onChange(isVisible);
}
}
render = () => {
return (
<View></View>
);
}
}
export default OnScreen;
react-navigation App.js
.......
const AppNav = AppNavigator(AppNavigators)
function getActiveRouteName(navigationState) {
if (!navigationState) {
return null;
}
const route = navigationState.routes[navigationState.index];
// dive into nested navigators
if (route.routes) {
return getActiveRouteName(route);
}
return route;
}
export default () =>
<Root>
<AppNav onNavigationStateChange={(prevState, currentState) => {
TempStore({type:'set',name:'_currentRoute',value:getActiveRouteName(currentState)})}}/>
</Root>;
AnyScreenYouWishToWatch.js
import OnScreen from '../../../helper/OnScreen';
......
OnActiveToggle=(str)=> {
if(str==='active'){
alert('active');}
else{
alert('inactive');}
}
.....
<OnScreen statekey={this.props.navigation.state.key} onChange={this.OnActiveToggle}/>