React Native Navigation with Redux - undefined is not a function - javascript

I try to setup react-native-navigation but I tun in problem
My code is following
app.js
import React from 'react';
import { Provider } from 'react-redux'
import { Navigation } from 'react-native-navigation';
import registerScreens from './screens'
import configureStore from './src/store/configureStore';
export default class App extends React.Component {
constructor(props) {
super(props)
const store = configureStore()
registerScreens(store, Provider);
startApp()
}
startApp() {
Navigation.startSingleScreenApp({
screen: {
screen: 'ior.Login',
title: 'Welcome',
navigatorStyle: {},
navigatorButtons: {}
},
drawer: {} ,
passProps: {},
animationType: 'slide-down'
});
}
}
configureStore.js
import ReduxThunk from 'redux-thunk'
import reducers from '../reducers'
import { createStore, applyMiddleware } from 'redux';
export default function configureStore() {
return createStore(
reducers,
{},
applyMiddleware(ReduxThunk)
);
}
screens.js
import { Navigation } from 'react-native-navigation';
import Login from './src/components/Login'
export function registerScreens(store, Provider) {
Navigation.registerComponent('ior.Login', () => Login, store, Provider);
}
Login.js
import React, { Component } from 'react'
import { connect } from 'react-redux'
import { StyleSheet, Text, View, TextInput, Button } from 'react-native';
import { loginChanged, passwordChanged, loginUser } from '../actions';
class Login extends React.Component {
onLoginChange(text) {
this.props.loginChanged(text)
}
onPasswordChange(text) {
this.props.passwordChanged(text)
}
onPress() {
this.props.loginUser(this.props.email, this.props.password)
}
render() {
return (
<View style={styles.container}>
<TextInput
style={styles.textField}
onChangeText={this.onLoginChange.bind(this)}
value={this.props.email}
placeholder={"Логин"}
/>
<TextInput
style={styles.textField}
onChangeText={this.onPasswordChange.bind(this)}
value={this.props.password}
placeholder={"Пароль"}
/>
<Button onPress={this.onPress.bind(this)} title={"Войти"}/>
</View>
)
}
}
const styles = StyleSheet.create({
textField: {
flex: 1,
width: '80%',
height: 100,
},
container: {
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
flex: 0.3,
marginTop: 210
},
button: {
width: '100%'
}
});
const mapStateToProps = state => {
return {
email: state.login.email,
password: state.login.password
}
}
export default connect(mapStateToProps, { loginChanged, passwordChanged, loginUser })(Login)
actions/index.js
import axios from 'axios'
export const loginChanged = (text) => {
return {
type: 'LOGIN_CHANGED',
payload: text
}
}
export const passwordChanged = (text) => {
return {
type: 'PASSWORD_CHANGED',
payload: text
}
}
export const loginUser = (email, password) => {
const creds = { mail: email, password: password }
console.log(creds)
return (dispact) => {
axios.post('http://192.168.1.10:3000/users/auth', creds)
.then(response => console.log(response))
.catch( err => console.log(err))
}
}
What am I doing wrong ?

The issue is that registerScreens is exported as a named export but you're importing it as a default export.
import registerScreens from './screens'
// ^ this is how you import a default export
You should add export default to registerScreens
export default function registerScreens(store, Provider) {
// ...
}
Or import it like a named export:
import { registerScreens } from './screens'
Additionally, you are calling a class method startApp() as if it was a normal function but it's a method on your class.
export default class App extends React.Component {
constructor(props) {
// ...
startApp()
// ^calling like a simple function
}
}
You must call it from the context:
export default class App extends React.Component {
constructor(props) {
// ...
this.startApp()
// ^calling it like a method
}
}

Related

Fix expo-media-library to load audio, and don't show pop up permission

I'm learning to create app music by Expo, but when I use expo-media-library, it doesn't show popup permission, so can't read file music on my devices.
File AudioProvider:
import { Alert, Text, View } from 'react-native';
import React, { Component,createContext } from 'react';
import * as MediaLibrary from 'expo-media-library';
export const AudioContext = createContext();
export class AudioProvider extends Component {
constructor(props){
super(props);
this.state={
audioFiles: []
}
}
permissionAllert = () => {
Alert.alert('Permission Required', 'This app needs to read audio files!', [
{
text: 'I am ready',
onPress: () => this.getPermission(),
},
{
text: 'cancle',
onPress: () => this.permissionAllert(),
},
]);
};
getAudioFiles = async () => {
let media = await MediaLibrary.getAssetsAsync({
mediaType:MediaLibrary.MediaType.audio,
});
media = await MediaLibrary.getAssetsAsync({
mediaType:MediaLibrary.MediaType.audio,
first: media.totalCount,
})
console.log(media.assets.length)
this.setState({...this.state, audioFiles:media.assets})
}
getPermission = async () =>{
// {
// "canAskAgain": true,
// "expires": "never",
// "granted": false,
// "status": "undetermined",
// }
const permission = await MediaLibrary.requestPermissionsAsync();
if(permission.granted){
//get all the file
this.getAudioFiles();
}
if(!permission.granted && permission.canAskAgain){
const {status,canAskAgain} = await MediaLibrary.requestPermissionsAsync();
if(status === 'denied' && canAskAgain){
//display alert
this.permissionAlert()
}
if(status==='granted'){
// get all the file
this.getAudioFiles();
}
if(status === 'denied' && !canAskAgain){
//display some error
}
}
}
componentDidMounth(){
this.getPermission()
}
render() {
return (
<AudioContext.Provider value={{audioFiles:this.state.audioFiles}}>
{this.props.children}
</AudioContext.Provider>
)
}
}
export default AudioProvider
File AudioList:
import { Text, View, StyleSheet, ScrollView } from 'react-native'
import React, { Component } from 'react'
import { AudioContext } from '../context/AudioProvider'
export class AudioList extends Component {
static contextType = AudioContext
render() {
return (
<ScrollView>
{this.context.audioFiles.map(item => <Text key={item.id}>{item.filename}</Text>)}
</ScrollView>
)
}
}
const styles = StyleSheet.create({
container:{
flex:1,
justifyContent:'center',
alignItems:'center'
}
})
export default AudioList
File App:
import React,{useState, useEffect} from 'react';
import { NavigationContainer } from '#react-navigation/native';
import AudioProvider from './app/context/AudioProvider';
import HomeNavigation from './app/navigation/HomeNavigation';
export default function App(){
return(
<AudioProvider>
<NavigationContainer>
<HomeNavigation/>
</NavigationContainer>
</AudioProvider>
)
}
I'm use:
expo (45.0), expo-media-library (14.1.0), react (17.0.2), react-native (0.68)
My Github:
https://github.com/MT1607/Project

React/Redux - TypeError: Cannot read property 'props' of undefined

i am a new in React, i am trying to create a dynamic NavBar with CoreUI. for now i have a static array in my action, so i can see it shows up with no errors on the Navigation bar.
but as soon as i run this i get an error. what i am trying to do is to create a new dynamic navigation bar and insert it into my static bar
// Admin Nav
import React, { Component } from "react";
import { getStoreType } from "../redux/actions/storeTypeActions";
import PropTypes from "prop-types";
import { connect } from "react-redux";
class AdminNav extends Component {
static propTypes = {
getStoreType: PropTypes.func.isRequired,
storeType: PropTypes.object.isRequired,
};
componentDidMount() {
this.props.getStoreType();
}
}
console.log("AdminNav", this.props);
const mapStateToProps = (state) => ({
storeType: state.storeType,
auth: state.auth,
});
export default connect(mapStateToProps, { getStoreType })(AdminNav);
//Reducer
import { GET_STORETYPE, STORETYPE_LOADING } from "../actions/types";
const initialState = {
items: [
{
title: true,
name: "ADMINISTRATOR",
wrapper: {
// optional wrapper object
element: "", // required valid HTML5 element tag
attributes: {}, // optional valid JS object with JS API naming ex: { className: "my-class", style: { fontFamily: "Verdana" }, id: "my-id"}
},
class: "", // optional class names space delimited list for title item ex: "text-center"
},
],
loading: false,
};
export default function (state = initialState, action) {
switch (action.type) {
case GET_STORETYPE:
return {
...state,
loading: false,
};
case STORETYPE_LOADING: {
return {
...state,
loading: true,
};
}
default:
return state;
}
}
//DefaultLayout.js
import React, { Component, Suspense } from "react";
import { Redirect, Route, Switch } from "react-router-dom";
import * as router from "react-router-dom";
import { Container } from "reactstrap";
import {
AppAside,
AppFooter,
AppHeader,
AppSidebar,
AppSidebarFooter,
AppSidebarForm,
AppSidebarHeader,
AppSidebarMinimizer,
AppBreadcrumb2 as AppBreadcrumb,
AppSidebarNav2 as AppSidebarNav,
} from "#coreui/react";
// Sidebar nav config (Owner/Admin)
import admin_navigation from "../_nav-admin";
// Routes Config
import routes from "../../routes";
import { connect } from "react-redux";
import PropTypes from "prop-types";
import { logout } from "../../redux/actions/authActions";
const DefaultAside = React.lazy(() => import("./DefaultAside"));
const DefaultFooter = React.lazy(() => import("./DefaultFooter"));
const DefaultHeader = React.lazy(() => import("./DefaultHeader"));
const AdminHeader = React.lazy(() => import("./AdminHeader"));
class DefaultLayout extends Component {
constructor(props) {
super(props);
this.state = {
role: "",
path: "",
dashboard: [],
};
}
loading = () => (
<div className="animated fadeIn pt-1 text-center">Loading...</div>
);
static propTypes = {
isAuthenticated: PropTypes.bool,
auth: PropTypes.object.isRequired,
logout: PropTypes.func.isRequired,
};
render() {
const { isAuthenticated } = this.props.auth;
// If NOT Authenticated, redirect to login
if (!isAuthenticated) {
this.props.history.push("/login");
}
const role = this.props.auth.user.role;
return (
<div className="app">
<div className="app-body">
<AppSidebar fixed display="lg">
<AppSidebarHeader />
<AppSidebarForm />
<Suspense>
<AppSidebarNav
navConfig={admin_navigation}
{...this.props}
router={router}
/>
</Suspense>
<AppFooter>
<Suspense fallback={this.loading()}>
<DefaultFooter />
</Suspense>
</AppFooter>
</div>
);
}
}
const mapStateToProps = (state) => ({
auth: state.auth,
});
export default connect(mapStateToProps, { logout })(DefaultLayout);
Here is a problem, you trying to access this not in a class method.
console.log("AdminNav", this.props);

ReferenceError: ReferenceError: Can't find variable: dispatch

I'm trying to use redux with react-native. I have created a fetch post data example app , then I just wanted to use with mapDispatchToProps method. I read the documentation and look at some tutorial, it looks similar.
Problem is when I try to use mapDispatchToProps its return error:
ReferenceError: ReferenceError: Can't find variable: dispatch
An error appears in HomeScreen
My Home Screen
import React from 'react';
import { View } from 'react-native';
import { connect } from 'react-redux';
import { getPosts } from '../actions/index';
class HomeScreen extends React.Component {
state = {
data:[],
}
componentDidMount() {
this.props.getPosts()
}
render() {
return (
<View style={styles.container}>
</View>
);
}
}
function mapStateToProps (state) {
return {
posts: state.posts
};
};
function mapDispatchToProps (dispatch) {
return {
getPosts: () => {
dispatch(getPosts())
}
};
};
export default connect(mapStateToProps, mapDispatchToProps)(HomeScreen)
My Store
import { createStore } from 'redux';
import rootReducer from '../reducers';
export default store = createStore(rootReducer);
My Action
import { GET_PGET_POST_LOADING,GET_POST_RECEIVED,GET_POST_ERROR } from './actionTypes';
import { GET_POST_URL } from '../api';
export const getPosts = () => {
dispatch({
type: GET_POST_LOADING
});
fetch(GET_POST_URL).then((data) => {
console.log(data);
dispatch({
type:GET_POST_RECEIVED,
payload:data
})
}).catch((error) => {
console.log(error)
})
}
My Reducer
import { GET_POST_LOADING, GET_POST_RECEIVED, GET_POST_ERROR } from '../actions/actionTypes';
const Post = (state = { posts: [] , loading: true }, action) => {
console.log(action);
switch(action.type) {
case GET_POST_LOADING:
return {
...state,
loading: true
}
case GET_POST_RECEIVED:
return {
loading:false,
posts: action.payload
}
case GET_POST_ERROR:
return state;
default: return state;
}
}
export default Post;
My Appjs
import React from 'react';
import { Platform, StatusBar, StyleSheet, View } from 'react-native';
import { AppLoading, Asset, Font, Icon } from 'expo';
import AppNavigator from './navigation/AppNavigator';
import { Provider } from 'react-redux';
import store from './store/index';
export default class App extends React.Component {
state = {
isLoadingComplete: false,
};
render() {
return (
<Provider store={store}>
<View style={styles.container}>
{Platform.OS === 'ios' && <StatusBar barStyle="default" />}
<AppNavigator />
</View>
</Provider>
);
}
}
I'm new about Redux, where I'm missing?
Thanks in advance :)

React navigation doesnt navigate

I am developing an application and using the listener onAuthStateChanged from Firebase in my AuthenticationLoadingScreen so I can redirect the user based on this state, however, it just opens a white page and doesn't open the home screen.
EDIT: Someone says that maybe the app.js is the problem so I added it here
import HomeScreen from '../screens/HomeScreen'
import AuthScreen from '../screens/AuthScreen'
// Implementation of HomeScreen, OtherScreen, SignInScreen, AuthLoadingScreen
// goes here.
const AppStack = createStackNavigator({ Home: HomeScreen});
const AuthStack = createStackNavigator({ Home: HomeScreen });
export default createAppContainer(createSwitchNavigator(
{
AuthLoading: AuthScreen,
App: AppStack,
Auth: AuthStack
},
{
initialRouteName: 'AuthLoading',
}
));
export default class AuthScreen extends React.Component {
constructor(props){
super(props);
}
componentDidMount = ()=>{
firebase.auth().onAuthStateChanged(user => {
this.props.navigation.navigate(user ? 'App' : 'Auth');
});
}
render() {
return (
<ImageBackground
source={require('../assets/images/AuthScreenBackground.png')}
style={styles.ImageBackground}/>
);
}
}
Here is the App.js code:
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import AppNavigation from './navigation/AppNavigation.js'
import * as firebase from 'firebase'
var config = {
};
firebase.initializeApp(config);
export default class App extends React.Component {
render() {
return (
<View style={styles.container}>
<AppNavigation/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
});
Try this code:
componentWillMount() {
this.observeLogin = firebase.auth().onAuthStateChanged(user => {
if (user) {
this.props.navigation.navigate('App');
} else {
this.props.navigation.navigate('Auth');
}
});
}
componentWillUnmount() {
// Don't forget to unsubscribe when the component unmounts
this.observeLogin ();
}

How to use StackNavigator with Redux?

Could please somebody help me to manage with StackNavigator and Redux integration? Everything looks pretty simple, but doesn't work.
index.ios.js
import React from 'react'
import {
AppRegistry
} from 'react-native'
import { Provider } from 'react-redux'
import configureStore from './configureStore'
import { StackNavigator } from 'react-navigation';
import Welcome from "./screens/welcome";
import Accounts from "./screens/accounts";
const store = configureStore()
const Nav = StackNavigator({
Welcome: {
screen: Welcome,
},
Accounts: {
screen: Accounts,
},
});
const TestApp = () => (
<Provider store={store}>
<Nav />
</Provider>
)
AppRegistry.registerComponent('TestApp', () => RNRedux)
configureStore.js
import { createStore } from 'redux'
import rootReducer from './reducers'
export default function configureStore() {
let store = createStore(rootReducer)
return store
}
reducers/index.js
import { combineReducers } from 'redux'
import accounts from './accounts'
const rootReducer = combineReducers({
accounts
})
export default rootReducer
screens/accounts.js
import React from 'react';
import { StyleSheet, Text, View, button } from 'react-native';
import { ListItem } from 'react-native-elements';
import { StackNavigator } from 'react-navigation';
import { connect } from 'react-redux';
export class Accounts extends React.Component {
static navigationOptions = {
title: 'Accounts',
}
constructor(props) {
super(props);
}
render() {
state = {}
const { navigate } = this.props.navigation;
return (
<View>
{
this.props.accounts.map((l, i) => (
<ListItem
key={i}
title={l.title}
subtitle={l.hash}
/>
))
}
</View>
);
}
}
function mapStateToProps (state) {
return {
accounts: state.accounts
}
}
export default connect(
mapStateToProps,
)(Accounts)
reducers/accounts.js
const initialState = {
accounts: [
{
title: "Bitcoin Slash Fund",
hash: "0x83247jfy344fgg",
},
],
}
export default function (state = initialState, action) {
switch (action.type) {
default:
return state;
}
}
When I navigate to Accounts screen, I get the error
TypeError: undefined is not a function (near '...this.props.state.accounts.map...');
Accounts screen seems not to be actually connected to Redux, and I can't figure out why. Any ideas? Thanks a lot.
Try this one:
function mapStateToProps (state) {
// Just FYI here you can use console.log to see the state)
// console.log(state);
return {
accounts: state.accounts.accounts
}
}
you could see console.log output in Xcode or in AndroidStudio.
Don't use Redux to manage the state of navigator. refer to this official doc: https://reactnavigation.org/docs/en/redux-integration.html
In my case, if you just want the title of navigator changed when the Redux state changes, just use screenProps, refer to: Passing screenProps to a tab navigator
e.g. in your App.js render method, pass screenProps into the target component,
import { LoginStackNavigator } from './navigators/LoginStackNavigator'
render () {
return (
<LoginStackNavigator screenProps={
{
// Step1. pass the value into the navigator component instance.
tradeTitle: i18n.t('trade', {locale: this.props.language}),
}
}/>
)
}
and in the related file, ( such as LoginStackNavigator.js in my case),
import { AppTabNavigator } from '../navigators/AppTabNavigator'
export const LoginStackNavigator = createStackNavigator({
Trade: {
screen: AppTabNavigator
}
//...
and in the final file ( AppTabNavigator)
export const AppTabNavigator = createBottomTabNavigator({
TradeStackNavigator: {
screen: TradeStackNavigator,
navigationOptions: ({navigation, navigationOptions, screenProps}) => {
return {
// Step2. here use screenProps to retrieve the value passed in .
tabBarLabel: screenProps.tradeTitle,
}
}

Categories

Resources