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
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
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);
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 :)
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 ();
}
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,
}
}