Display fullscreen image when state is loading using Redux - javascript

I have a fullscreen image I would like to display when my app state is loading. How can set this up?
I would like to implement something like this:
if (videos == "") {
return (
<View style={styles.imageContainer}>
<Image
style={styles.image}
source={require("../assets/images/tc-logo.png")}
/>
</View>
);
}
My current app.js looks like this
export default class App extends React.Component {
runInitialAppStartActions = () => {
store.dispatch(fetchData());
};
render() {
return (
<ImageBackground
source={require("./assets/images/TC_background.jpg")}
style={styles.container}
>
<Provider store={store}>
<PersistGate
loading={null}
persistor={persistor}
onBeforeLift={this.runInitialAppStartActions}
>
<AppNavigator
ref={navigatorRef => {
NavigationService.setTopLevelNavigator(navigatorRef);
}}
/>
</PersistGate>
</Provider>
</ImageBackground>
);
}
}

Sory, i can't write comment, i need 50 reputation for comments.So I'm writing as an answer.
Im new in react, maybe you can solve with componentDidMount() method.
You can look this question: Stop rendering of a component after componentDidMount()

You can simply do it like this. I just assumed that you have a state named videos.
import React, {Component} from 'react';
import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';
import * as videoAction from '../actions/videoAction.js';
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
videos: ''
};
}
async componentDidMount() {
await this.props.videoAction.getVideo();
this.setState({
videos: this.props.videoState.videos
});
}
runInitialAppStartActions = () => {
store.dispatch(fetchData());
};
render() {
const {videos} = this.state;
if (videos == "") {
return (
<View style={styles.imageContainer}>
<Image
style={styles.image}
source={require("../assets/images/tc-logo.png")}
/>
</View>
);
}else{
return (
<ImageBackground
source={require("./assets/images/TC_background.jpg")}
style={styles.container}
>
<Provider store={store}>
<PersistGate
loading={null}
persistor={persistor}
onBeforeLift={this.runInitialAppStartActions}
>
<AppNavigator
ref={navigatorRef => {
NavigationService.setTopLevelNavigator(navigatorRef);
}}
/>
</PersistGate>
</Provider>
</ImageBackground>
);
}
}
}
const mapStateToProps = (state) => {
return {
videoState: state.videoState
};
};
const mapDispatchToProps = (dispatch) => {
return{
videoAction: bindActionCreators(videoAction, dispatch)
};
};
export default connect(mapStateToProps, mapDispatchToProps)(App);

Related

ERROR: Touchable child must either be native or forward setNativeProps to a native component

I am currently doing ReactNative course from coursera and the course is 4 years old and i am facing this error: Touchable child must either be native or forward setNativeProps to a native component.
I've no idea what this is. It will be greatly helpful if someone will help me.Adding files details as well:
App.js
import React from 'react';
import Main from './components/MainComponent';
export default class App extends React.Component {
render() {
return (
<Main />
);
}
}
MainComponent.js
import React, { Component } from 'react';
import Menu from './MenuComponent';
import { DISHES } from '../shared/dishes';
import Dishdetail from './DishdetailComponent';
import { View } from 'react-native';
class Main extends Component {
constructor(props) {
super(props);
this.state = {
dishes: DISHES,
selectedDish: null,
};
}
onDishSelect(dishId) {
this.setState({selectedDish: dishId})
}
render() {
return (
<View style={{flex:1}}>
<Menu dishes={this.state.dishes} onPress={(dishId) => this.onDishSelect(dishId)} />
<Dishdetail dish={this.state.dishes.filter((dish) => dish.id === this.state.selectedDish)[0]} />
</View>
);
}
}
export default Main;
MenuComponent.js
import React from 'react';
import { View, FlatList } from 'react-native';
import { ListItem } from 'react-native-elements';
function Menu(props) {
const renderMenuItem = ({item, index}) => {
return (
<View>
<ListItem
key={index}
title={item.name}
subtitle={item.description}
hideChevron={true}
onPress={() => props.onPress(item.id)}
leftAvatar={{ source: require('./images/uthappizza.png')}}
/>
</View>
);
};
return (
<View>
<FlatList
data={props.dishes}
renderItem={renderMenuItem}
keyExtractor={item => item.id.toString()}
/>
</View>
);
}
export default Menu;
Dishdetailcomponent.js
import React from 'react';
import { Text, View } from 'react-native';
import { Card } from 'react-native-elements';
function Dishdetail(props) {
return(
<View >
<RenderDish dish={props.dish} />
</View>
);
}
function RenderDish(props) {
const dish = props.dish;
if (dish != null) {
return(
<View>
<Card
featuredTitle={dish.name}
image={require('./images/uthappizza.png')}>
<Text style={{margin: 10}}>
{dish.description}
</Text>
</Card>
</View>
);
}
else {
return(<View></View>);
}
}
export default Dishdetail;
Help will be appreciated!!
Thanks
I had same issue some days before. Quickfix for this issue.
import TouchableOpacity form 'react-native';
Add following in the MenuComponent.js
<ListItem
Component={TouchableOpacity}
key={item.id}
title={item.name}
subtitle={item.description}
hideChevron={true}
onPress={() => props.onPress(item.id)}
leftAvatar={{ source: require('./images/uthappizza.png')}}
/>
and run the program again. This will fix your problem.

React-Native Router Flux with Netwoking and Sceenchooser

I have a problem.
My App work right now but not like how I want.
App.js
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
data: [],
isLoading: true,
};
}
componentDidMount() {
fetch('https://reactnative.dev/movies.json')
.then((response) => response.json())
.then((json) => {
this.setState({ data: json.movies });
})
.catch((error) => console.error(error))
.finally(() => {
this.setState({ isLoading: false });
});
}
render() {
const { data, isLoading } = this.state;
const goToPageTwo = () => Actions.sw({text: 'Hello World!'});
return (
<View style={{ flex: 1, padding: 24 }}>
{isLoading ? <ActivityIndicator/> : (
<FlatList
data={data}
keyExtractor={({ id }, index) => id}
renderItem={({ item }) => (
<TouchableOpacity onPress={() => { Actions.hp({text: item.id}) }}>
<Text>{item.title}</Text>
</TouchableOpacity>
)}
/>
)}
</View>
);
}
};
index.js / Route.js in my case sm.js
import app from './App';
import sw from './StarWars'
import bttf from './BacktotheFuture'
import hP from './handlePage';
import tM from './theMatrix';
import iN from './Inception';
const SceneManager = () => (
<Router>
<Scene>
<Scene key='home'
component={app}
title='BTour'
initial
/>
<Scene key='sw'
component={sw}
title='star wars'
/>
<Scene key='hp'
component={hP}
title='BTour'
/>
<Scene key='bttf'
component={bttf}
title='Back to the future'
/>
<Scene key='tM'
component={tM}
title='MAtrix'
/>
<Scene key='iN'
component={iN}
title='Inception'
/>
</Scene>
</Router>
)
export default SceneManager;
and my Handlepage.js
import StarWars from './StarWars';
import BTTF from './BacktotheFuture';
import TM from './theMatrix';
import IN from './Inception';
export default class handlePage extends Component {
renderElement() {
if(this.props.text ==1) {
return <StarWars/>
}
if (this.props.text ==2) {
return <BTTF/>
}
if (this.props.text ==3) {
return <TM/>
}
if(this.props.text == 4) {
return <IN/>
}
return null;
}
render(){
return(
this.renderElement()
)
}
};
NOW MY PROBLEM:
I want to use the Scene what I have defined in my Router class. For example when I press the first button in the Home Screen then "Star Wars" will be open but not the Component what I write in the route class.
Can I take the Component Scene from Route.js to the HandlePage.js in the If-Statemant OR can I put the If Statemant in the Router class.
Right now only the script in the IF-Statemant will open.
I don't think defining handlePage as class is necessary, you can just declare a function to navigate to your scene depending on item.id
Handlepage.js
import { Actions } from 'react-native-router-flux';
export const navigateByItemId = (id) => {
switch (id) {
case 1:
Actions.jump('sw');
break;
case 2:
Actions.jump('bttf');
break;
case 3:
Actions.jump('tM');
break;
default:
Actions.jump('iN');
}
};
And in App.js you can call this utility function to decide where to navigate
import { navigateByItemId } from './Handlepage';
...
<TouchableOpacity onPress={() => { navigateByItemId(item.id) }}>
<Text>{item.title}</Text>
</TouchableOpacity>
You can delete handlePage declaration in your router:
<Scene key='hp' //you can delete this code
component={hP}
title='BTour'
/>

changing the language of react native app does not change the language for already opened routes

if i change the language from my setting screen inside my app, it does not change the language for already opened routes in my application. the language change is only reflect on unopened routes. i used react-native-localize and i18n-js. Given below my code
index.js
import * as RNLocalize from 'react-native-localize';
import I18n from 'i18n-js';
import memoize from 'lodash.memoize';
import {I18nManager,
AsyncStorage} from 'react-native';
import en from './en';
import am from './am';
import or from './or';
import tg from './tg';
import sl from './sl';
const locales = RNLocalize.getLocales();
if (Array.isArray(locales)) {
I18n.locale = locales[0].languageTag;
}
I18n.fallbacks = true;
I18n.translations = {
default: en,
'en-US': en,
en,
am,
or,
tg,
sl,
};
export default I18n;
My SettingScreen where i can change the language is:
SettingScreen.js
const listLanguage = [
{key:'en', label:'En'}, {key:'am', label:'Am'} ,{key:'or', label: 'Or'}, {key:'tg', label:'TG'},]
export default class SettingsScreen extends React.Component {
constructor(props) {
super(props);
this.state = { visible: true ,
languageSelected: 'en'
};
}
backToMain() {
this.props.navigation.navigate('LocationTrackingScreen', {});
}
handleBackPress = () => {
this.props.navigation.navigate('LocationTrackingScreen', {});
return true;
};
hideSpinner() {
this.setState({ visible: false });
}
componentDidMount() {
BackHandler.addEventListener('hardwareBackPress', this.handleBackPress);
}
componentWillUnmount() {
BackHandler.removeEventListener('hardwareBackPress', this.handleBackPress);
}
onChangeLanguage(languageSelected){
this.setState({
languageSelected
})
I18n.locale = languageSelected
}
render() {
const {languageSelected} = this.state
return (
<SafeAreaView style={styles.container}>
<View style={styles.headerContainer}>
<TouchableOpacity
style={styles.backArrowTouchable}
onPress={() => this.backToMain()}>
<Image style={styles.backArrow} source={backArrow} />
</TouchableOpacity>
<Text style={styles.headerTitle}>{I18n.t('setting.setting_title')}</Text>
</View>
<View style={styles.containerLangSelect}>
<Text style={styles.sectionDescription}>{I18n.t('setting.select_language')}</Text>
</View>
<View style={styles.containerDropdown}>
<DropdownLanguage language={languageSelected} onChangeLanguage={this.onChangeLanguage.bind(this)}></DropdownLanguage>
</View>
</SafeAreaView>
);
}
}
class DropdownLanguage extends React.Component {
constructor(props) {
super(props)
}
render() {
return (
<View style={styles.dropdownLanguage}>
{/* <Text style={{width:10,}}>{I18n.t('setting.select_language')}: </Text> */}
<Picker
mode="dropdown"
iosHeader={''}
style={{ width: width,
}}
selectedValue={this.props.language}
onValueChange={this.props.onChangeLanguage.bind(this)}
>
{listLanguage.map((languageItem, i) => {
return <Picker.Item key={i} value={languageItem.key} label= {languageItem.label} />
})}
</Picker>
</View>
)
}
}

React Native - Can't display the Data in other screen

What I want to achieve is display the datas in other screen or another component with React Redux. I'm using the latest version of React Redux and Redux.
My problem is every time I want to display the data, or when I press the button (TouchableOpacity) in EventCreator.js it doesn't display. I tried to check all of my codes but I don't see any typo or any wrong codes.
Feel free to ask for more of my codes. Thank you!
UPDATE: I tried all codes to my another new project, but with RNNV1. So it might be some new codes for RNNv2 that is related to React Redux to change. I prefer to all viewers to focus check my codes about RNNv2 connected to React Redux. Thank you!
These are my codes:
App.js, all my Registered Screens.
import {Navigation} from 'react-native-navigation';
import React from 'react';
//Screens
import AuthScreen from './src/screens/Auth/Auth';
import EventMap from './src/screens/Map/Map';
import EventCreator from './src/screens/EventCreator/EventCreator';
import EventHome from './src/screens/Home/Home';
import EventPushScreen from './src/screens/EventPushScreen/EventPushSc';
//Redux
import { Provider } from 'react-redux';
import configureStore from './src/store/configureStore';
const store = configureStore();
//Register Screens
Navigation.registerComponentWithRedux("Event.AuthScreen", () => AuthScreen);
Navigation.registerComponentWithRedux("Event.Map", () => EventMap);
Navigation.registerComponent("EventCreator", () => (props) => (
<Provider store={store}>
<EventCreator {...props}/>
</Provider>
), () => EventCreator);
Navigation.registerComponent("EventHome", () => (props) => (
<Provider store={store}>
<EventHome {...props}/>
</Provider>
), () => EventHome);
//Start A App
Navigation.events().registerAppLaunchedListener(() => {
Navigation.setRoot({
root: {
stack: {
children: [{
component: {
name: "Event.AuthScreen",
}
}],
options: {
topBar: {
title: {
text: 'Welcome',
alignment: 'center'
}
}
}
}
}
});
});
This is my 1st Screen where the TextInput and Button (TouchableOpacity) is.
EventCreator.js
import EventInput from '../../components/EventInput';
class EventCreator extends Component {
eventAddedHandler = (eventName) => {
this.props.onAddEvent(eventName);
};
render() {
return (
<View style={styles.container}>
<EventInput onEventAdded={this.eventAddedHandler}/>
</View>
);
}
};
const mapDispatchToProps = dispatch => {
return {
onAddEvent: (eventName) => dispatch(addEvent(eventName))
};
};
export default connect(null, mapDispatchToProps)(EventCreator);
EventInput.js, This is my Component that is connected to EventCreate.js
class EventInput extends Component {
state = {
eventName: ""
};
eventNameChangedHandler = (val) => {
this.setState({
eventName: val
});
};
eventSubmitHandler = () => {
if (this.state.eventName.trim() === "") {
return;
}
this.props.onEventAdded(this.state.eventName);
};
render () {
return (
<View style={styles.inputAndButtonContainer}>
<TextInput
placeholder="Create your event"
value={this.state.eventName}
onChangeText={this.eventNameChangedHandler}
style={styles.textInputContainer}
/>
<TouchableOpacity onPress={this.eventSubmitHandler}>
<View style={styles.buttonContainer}>
<Text style={{color: 'black'}}>Add</Text>
</View>
</TouchableOpacity>
</View>
);
}
};
Home.js, this is where I want to display may Data or the FlatList.
class Home extends Component {
eventSelectedHandler = key => {
const selEvent = this.props.events.find(event => {
return event.key === key;
});
Navigation.push("EventHomeStack", {
component: {
name: "EventPushScreen",
passProps: {
selectedEvent: selEvent
},
options: {
topBar: {
title: {
text: selEvent.name
}
}
}
}
});
};
render() {
return (
<View>
<EventList
events={this.props.events}
onItemSelected={this.eventSelectedHandler}
/>
</View>
);
}
};
const mapStateToProps = state => {
return {
events: state.events.events
};
};
export default connect(mapStateToProps)(Home);
EventList.js, another Component connected to Home.js
import ListItem from './ListItem';
const eventList = (props) => {
return (
<FlatList
style={styles.listContainer}
data={props.events}
renderItem={(info) => (
<ListItem
eventName={info.item.name}
eventImage={info.item.image}
onItemPressed={() => props.onItemSelected(info.item.key)}
/>
)}
/>
);
};
export default eventList;
listItem.js, another Component connected to EventList.js
const listItem = (props) => (
<TouchableOpacity onPress={props.onItemPressed}>
<View style={styles.listItem}>
<Image resizeMode="cover" source={props.eventImage} style={styles.eventImage}/>
<Text>
{props.eventName}
</Text>
</View>
</TouchableOpacity>
);
export default listItem;
events.js (reducer)
import {ADD_EVENT, DELETE_EVENT} from '../actions/actionTypes';
const initialState = {
events: []
};
const reducer = (state = initialState, action) => {
switch(action.type) {
case ADD_EVENT:
return {
...state,
events: state.events.concat({
key: `${Math.random()}`,
name: action.eventName,
image: {
uri: "https://c1.staticflickr.com/5/4096/4744241983_34023bf303_b.jpg"
}
})
};
case DELETE_EVENT:
return {
...state,
events: state.events.filter(event => {
return event.key !== action.eventKey;
})
};
default:
return state;
}
};
export default reducer;

Use Navigator in React Native + Redux

I'm new to React Native.
I have a React Native app using the Redux framework. I'm using the Navigator component to handle navigation but this.props.navigator is undefined in component. How can I pass "this.props.navigator" to component?
I'm not able to find any good examples of how to do it correctly so I'm looking for some help and clarification.
index.anroid.js
...
import App from './app/app';
AppRegistry.registerComponent('RnDemo', () => App);
app.js
...
import App from './containers/app';
const logger = createLogger();
const createStoreWithMiddleware = applyMiddleware(thunk, logger)(createStore);
const store = createStoreWithMiddleware(rootReducer);
const rootApp = () => {
return (
<Provider store={store}>
<App />
</Provider>
)
}
export default rootApp;
containers/app.js
...
class App extends Component {
renderScene(route, navigator) {
let Component = route.component
return (
<Component navigator={navigator} route={route} />
)
}
configureScene(route) {
if (route.name && route.name === 'Home') {
return Navigator.SceneConfigs.FadeAndroid
} else {
return Navigator.SceneConfigs.FloatFromBottomAndroid
}
}
_selectPage(page) {
if(page === 'detail') {
this.props.navigator.push({
component: Detail,
name: 'Detail'
}) // **this.props.navigator.push is not a function**
}
}
render() {
const { navigator } = this.props;
console.log(navigator); // **>>>>>> Undefined**
return (
<View style={styles.container}>
<View style={styles.menu}>
<TouchableOpacity onPress={() => this._selectPage('detail')}><View style={styles.menuItem}><Text>Detail</Text></View></TouchableOpacity>
</View>
<View style={styles.content}>
<Navigator
ref='navigator'
style={styles.navigator}
configureScene={this.configureScene}
renderScene={this.renderScene}
initialRoute={{
component: Home,
name: 'Main'
}}
/>
</View>
</View>
)
}
}
renderScene(route, navigator) {
let Component = route.component
return (
// <Component navigator={navigator} route={route} />
<Component {...this.props} navigator={navigator} route={route} />
)
}
Try it

Categories