I need to fix bug with react native. what is the problem? - react-native

Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
You might have mismatching versions of React and the renderer (such as React DOM)
You might be breaking the Rules of Hooks
You might have more than one copy of React in the same app
import React, { PureComponent, useState } from 'react'
import { StoryContainer } from 'react-native-stories-view'
import {
TouchableOpacity,
Alert,
StyleSheet,
View,
Text,
SafeAreaView,
ImageBackground,
Image,
Platform,
StatusBar,
} from 'react-native'
import { connect } from 'react-redux'
class StoryViewScreen extends PureComponent {
constructor(props) {
super(props);
this.state = {
}
}
render() {
const { files } = this.props.route.params;
const fileUrls = [];
for (var i = 0; i < files.length; i++) {
fileUrls.push(files[i].uri);
}
console.log("files path:", fileUrls);
return (
<View style={{ flex: 1, flexDirection: 'column' }}>
{Platform.OS === 'ios' && (
<View style={{
backgroundColor: 'gray',
height: 45,
}}>
<StatusBar barStyle="light-content" backgroundColor={'green'} />
</View>
)}
{Platform.OS === 'android' && (
<StatusBar barStyle="dark-content" backgroundColor={'white'} />
)}
<SafeAreaView style={{ flex: 1, flexDirection: 'column', backgroundColor: 'gray' }}>
<StoryContainer
visible={true}
enableProgress={false}
images={fileUrls}
duration={5}
containerStyle={{
width: '100%',
height: '100%',
}} />
{/* <Text>This is teh realdksfjdsklfj</Text> */}
</SafeAreaView>
</View>
);
}
};
const style = StyleSheet.create({
});
function mapStateToProps(state) {
return {
// currentUser: state.user.currentUser,
};
}
function mapDispatchToProps(dispatch) {
return {
dispatch
};
}
export default connect(mapStateToProps, mapDispatchToProps)(StoryViewScreen);

You cannot use useState in class component, instead use setState to set the state.

Related

How to write Custom flash message in react native

I want to display a custom message after successful record update when boolean value of recordUpdateSuccess become true and after 3seconds it should disappear.
{recordUpdateSuccess ? this.renderRecordUpdatedSucess() : null}
I have function to display message:
renderRecordUpdatedSucess = () => (
<View style={styles.sucessAlert}>
<Text style={styles.sucessAlert}>Record updated successfully.</Text>
</View>
)
I tried to use setTimeout() to display message but not working.
Any idea to acheive this one.
I don't want to use Toast, any third party library for this one.
Custom flash message (No external Library)
Working Example: https://snack.expo.io/#msbot01/1dcddc
import * as React from 'react';
import { Text, View, StyleSheet, TouchableOpacity } from 'react-native';
import Constants from 'expo-constants';
// You can import from local files
import AssetExample from './components/AssetExample';
// or any pure javascript modules available in npm
import { Card } from 'react-native-paper';
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {
flashMessage: false
}
}
onPress(){
this.setState({
flashMessage: true
},()=>{setTimeout(() => this.closeFlashMessage(), 3000)})
}
closeFlashMessage(){
this.setState({
flashMessage: false
})
}
render() {
return (
<View style={styles.container}>
<TouchableOpacity onPress={()=>{this.onPress()}}>
<Text>Click Me</Text>
</TouchableOpacity >
{this.state.flashMessage==true?
<View style={styles.flashMessage}>
<Text style={{color:'white'}}>This is custom Flash message</Text>
</View>
:
null
}
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
padding: 8,
},
flashMessage:{
position:'absolute',
backgroundColor:'green',
width:'100%',
justifyContent:'center',
alignItems:'center',
height:40,
top:0
}
});

React-Native Constructor

Please help me find what is wrong in the following React-Native code?
It says after constructor (props) should have ';' semicolon. I don't know if I declared it in the right way.
import React from 'react';
import { StyleSheet, TextInput, View } from 'react-native';
export default function App() {
constructor (props){
this.state = {
text: 'HI'
}
}
render () {
return (
<View style={styles.container}>
<TextInput style={styles.input}
placeholder = 'Enter Value...'
placeholderTextColor ='#E74292'
onChangeText = {(text) => {
this.setState({text})
}}
/>
</View>
);
}
const styles = StyleSheet.create({
container:{
flex:1,
backgroundColor:'#F4C724',
},
input :{
marginTop:30,
height:30,
width:30,
borderWidth:2,
padding:10,
borderRadius: 5,
borderColor:'#1287A5'
}
}
);
You should declare the component as class instead of function if you want a constructor:
import React from 'react';
import { StyleSheet, TextInput, View } from 'react-native';
export default class App {
constructor(props) {
this.state = {
text: 'HI'
};
}
render() {
return (
<View style={styles.container}>
<TextInput
style={styles.input}
placeholder="Enter Value..."
placeholderTextColor="#E74292"
onChangeText={text => {
this.setState({ text });
}}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#F4C724'
},
input: {
marginTop: 30,
height: 30,
width: 30,
borderWidth: 2,
padding: 10,
borderRadius: 5,
borderColor: '#1287A5'
}
});
constructor only works in class based component so switch to class based component rather than . functional whihc is now.
import React from 'react';
import { StyleSheet, TextInput, View } from 'react-native';
export default class App extends React.Component{
constructor(props) {
this.state = {
text: 'HI'
};
}
render() {
return (
<View style={styles.container}>
<TextInput
style={styles.input}
placeholder="Enter Value..."
placeholderTextColor="#E74292"
onChangeText={text => {
this.setState({ text });
}}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#F4C724'
},
input: {
marginTop: 30,
height: 30,
width: 30,
borderWidth: 2,
padding: 10,
borderRadius: 5,
borderColor: '#1287A5'
}
});
You need to study the difference between functional and class component.
Functional component is just a plain java-script function which also known as stateless component. They do not manage their own state or have access to the lifecycle methods.
for more please follow the link below:
https://medium.com/#Zwenza/functional-vs-class-components-in-react-231e3fbd7108
you can use useState , the dynamic function value loads to the initial variable on load
import React,{ useState } from 'react';
import { View, Text, Button, ImageBackground} from 'react-native';
export default function Home({navigation}){
//function getversion onload
const [initval,setInitval] = useState(()=>{ return '123456'});
return(
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text> {initval} </Text>
</View>
);
}
You cannot have a constructor() in functional components. You should either change function component to class component or go and check out the react doc about React Hooks. You are going to have a better understanding of the differences between react class components and react functional components.

Force unmounting on screen change

I recently integrated React Redux and Redux Thunk into my application in the hope that it would better allow me to manage state across screens.
However, using my navigation library (react native router flux), when ever I navigate between screens I get warnings of trying to set state across unmounted components and I am not sure what I would even need to unmount in componentWillUnmount as no calls should happen after a screen navigation.
My question then is, how can I force unmount everything on componentWillUnmount? Is there something built into React Native that I should use? Or, in my navigation library?
import React, { Component } from 'react';
import { View, Text, StyleSheet } from 'react-native';
import * as Font from 'expo-font'
class CustomText extends Component {
async componentDidMount() {
await Font.loadAsync({
'varelaround-regular': require('../../../assets/fonts/varelaround-regular.ttf'),
'opensans-regular': require('../../../assets/fonts/opensans-regular.ttf'),
'opensans-bold': require('../../../assets/fonts/opensans-bold.ttf'),
});
this.setState({ fontLoaded: true });
}
state = {
fontLoaded: false,
};
setFontType = type => {
switch (type) {
case 'header':
return 'varelaround-regular';
case 'bold':
return 'opensans-bold';
default:
return 'opensans-regular';
}
};
render() {
const font = this.setFontType(this.props.type ? this.props.type : 'normal');
const style = [{ fontFamily: font }, this.props.style || {}];
const allProps = Object.assign({}, this.props, { style: style });
return (
<View>
{
this.state.fontLoaded ? (
<Text {...allProps}>{this.props.children}</Text>
) : <Text></Text>
}
</View>
);
}
}
export default CustomText;
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center'
}
});
And one of my screens:
import React from "react";
import { ActivityIndicator, Image, StyleSheet, View } from "react-native";
import { Actions } from "react-native-router-flux";
import { connect } from "react-redux";
import * as profile from "../actions/profile";
import {
CustomText
} from "../components/common/";
class Home extends React.Component {
componentDidMount() {
this.props.loadProfile();
}
renderScreen() {
return (
<View style={{ flex: 1 }}>
<View style={{ flex: 0.3 }}>
<CustomText type="header" style={styles.headerTextStyle} onPress={() => Actions.home()}>
Hello {this.props.name}!
</CustomText>
</View>
</View>
);
}
renderWaiting() {
return (
<GradientBackground type="purple">
<View
style={{ flex: 1, justifyContent: "center", alignItems: "center" }}
>
<ActivityIndicator size="large" color="#FFF" />
</View>
</GradientBackground>
);
}
render() {
return (
<View style={{ flex: 1 }}>
{this.props.isLoading == true
? this.renderWaiting()
: this.renderScreen()}
</View>
);
}
}
function mapStateToProps(state) {
return {
name: state.profile.profile.friendly_name,
isLoading: state.profile.isLoading,
error: state.profile.error
};
}
function mapDispatchToProps(dispatch) {
return {
loadProfile: () => dispatch(profile.loadProfile())
};
}
export default connect(
mapStateToProps,
mapDispatchToProps
)(Home);
const styles = StyleSheet.create({
headerTextStyle: {
color: "#FFFFFF",
fontSize: 40,
textAlign: "center",
marginVertical: 50
},
basicViewStyle: {
flex: 1
}
});

Open a WebView after a button pressed with reactNative

I am developing a mobile app with React Native. I want to open a WebView after a button pressed. Here is my code, but its not working. The button onPress method is not working.
import React, { Component } from 'react';
import { View, StyleSheet, Button, WebView } from 'react-native';
import { Constants } from 'expo';
export default class webView extends Component {
onNavigationStateChange = navState => {
if (navState.url.indexOf('https://www.google.com') === 0) {
const regex = /#access_token=(.+)/;
const accessToken = navState.url.match(regex)[1];
console.log(accessToken);
}
};
renderContent() {
return (
<WebView
source={{
uri: '',
}}
onNavigationStateChange={this.onNavigationStateChange}
startInLoadingState
scalesPageToFit
javaScriptEnabled
style={{ flex: 1 }}
/>
);
}
render() {
return (
<View style={styles.container}>
<Button
style={styles.paragraph}
title="Login"
onPress={() => this.renderContent()}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
},
});
I tried onPress={this.renderContent()} this also, but it give an exception. What can I do ?
You aren't rendering your WebView in the the render() method of the Component. Just think of render as your DOM of the webpage. You need to provide the component a place in the render component, than you can remove it or add it, see i am calling the renderContent from the render method. So whenever the state variable showWebView is true it will render the WebView You should do something like this:
import React, { Component } from 'react';
import { View, StyleSheet, Button, WebView } from 'react-native';
import { Constants } from 'expo';
export default class webView extends Component {
state={
showWebView: false
}
onNavigationStateChange = navState => {
if (navState.url.indexOf('https://www.google.com') === 0) {
const regex = /#access_token=(.+)/;
const accessToken = navState.url.match(regex)[1];
console.log(accessToken);
}
};
renderContent() {
return (
<WebView
source={{
uri: '',
}}
onNavigationStateChange={this.onNavigationStateChange}
startInLoadingState
scalesPageToFit
javaScriptEnabled
style={{ flex: 1 }}
/>
);
}
render() {
return (
<View style={styles.container}>
{ this.state.showWebView && this.renderContent() }
<Button
style={styles.paragraph}
title="Login"
onPress={() => this.setState({showWebView: true})}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
},
});
I think you must import the following
import { WebView } from 'react-native-webview'
instead of
'react'

React Native : Access to component ref child in FlatList

I'm not able to access to component ref child in FlatList. On componentDidMount method, I've only one ref for the FlatList.
Here is my code in case you want to reproduce it:
import React, { Component } from "react";
import {
AppRegistry,
FlatList,
StyleSheet,
Text,
View
} from "react-native";
export default class touchable extends Component {
render() {
return (
<View style={styles.container}>
<FlatList
ref="REF-FLATLIST"
data={[{ key: "a" }, { key: "b" }]}
renderItem={({ item }) =>
<Text ref={`REF-FLATLIST${item.key}`}>
{item.key}
</Text>}
/>
</View>
);
}
componentDidMount() {
console.log(this.refs);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: "center",
alignItems: "center",
backgroundColor: "#F5FCFF"
}
});
AppRegistry.registerComponent("touchable", () => touchable);
I'm using React Native v0.45.1.
you can set it the ref using the ref callback this way:
import React, { Component } from "react";
import {
AppRegistry,
FlatList,
StyleSheet,
Text,
View
} from "react-native";
export default class touchable extends Component {
render() {
return (
<View style={styles.container}>
<FlatList
ref="REF-FLATLIST"
data={[{ key: "a" }, { key: "b" }]}
renderItem={({ item }) =>
<Text ref={(ref) => this.textRef = {...this.textRef, [`REF-FLATLIST${item.key}`]: ref}}>
{item.key}
</Text>}
/>
</View>
);
}
componentDidMount() {
console.log(this.refs, this.textRef);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: "center",
alignItems: "center",
backgroundColor: "#F5FCFF"
}
});