I am following this video tutorial on Redux. I followed the code exactly as the person from the tutorial but when the app renders I get an error saying -
TypeError: undefined is not an object (evaluating 'this.state'
Here's the error stack:
And here's the code that I use for the component:
import React from 'react'
import {View, Text, StyleSheet, TextInput, TouchableOpacity} from 'react-native'
import {Ionicons} from '#expo/vector-icons'
import {connect} from 'react-redux' // used to connect the Store with this component
function AddTodo() {
state = {
text: ''
}
addTodo = (text) => {
this.props.dispatch({type:'ADD_TODO', text})
this.setState({text: ''})
}
return (
<View style={{flexDirection: 'row', marginHorizontal: 20}}>
<TextInput
onChangeText={ (text) => this.setState({text})}
value={this.state.text}
placeholder="Eg. Create new Video"
style={{borderWidth: 1, borderColor:'#eaeaea',
backgroudColor:'#f2f2e1', height: 50, flex:1, padding: 5}} />
<TouchableOpacity onPress={() => this.addTodo(this.state.text)}>
<View style={{height:50, backgroundColor:'#f2f2e1', alignItems:'center', justifyContent:'center'}}>
<Ionicons name="md-add" size={30} style={{color:'#de9595', padding:10}}/>
</View>
</TouchableOpacity>
</View>
)
}
export default connect()(AddTodo) //This is how we connect the Store with the component
const styles = StyleSheet.create({
container:{
flex:1,
alignItems:'center',
justifyContent:'center'
}
})
Why am I getting this error?
You can only use this in a class, referring to the instance of that class. In your functional components you cannot have a persistent state without using the hook useState.
Do this instead:
const [state, setState] = useState({text: ''});
And access use your state like so: state.text.
Always call your hooks at the top level, before conditionals and renders.
Related
import { StyleSheet, Text, View, ImageBackground, SafeAreaView } from 'react-native';
import react, {useState} from 'react';
import InputComponent from './sharedComponent/InputComponent';
import ButtonComponent from './sharedComponent/ButtonComponent';
export default function App() {
const[text, setText] = useState('');
const[todoList, setToDoList] = useState([]);
return (
<ImageBackground
source={require('./assets/todoimages.png')}
style={{width: '100%', height: '100%'}}
>
<SafeAreaView>
<View style={styles.container}>
<InputComponent onchangeValue={setText}
/>
<ButtonComponent
addItem={setToDoList}
itemToAdd={text}
/>
</View>
<View>
{todoList.length > 0 && todoList.map((value) => <Text>{value}</Text>)}
</View>
</SafeAreaView>
</ImageBackground>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'baseline',
justifyContent: 'center',
paddingBottom:'10%'
},
});
I am getting the error :
Error: Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.
can anyone tell me why I am getting the error and what is the solution for that?
below is the button component:
import {View,Button, StyleSheet} from 'react-native';
const ButtonComponent = (props) =>{
return(
<View style={styles.container}>
<View style={styles.buttonContainer}>
<Button
onPress={props.addItem(prevArray=> [...prevArray, props.itemToAdd])}
title="ADD"
/>
</View>
</View>
)
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
},
buttonContainer: {
margin: 20
},
})
export default ButtonComponent;
below is the input component:
import { Text, TextInput, View } from 'react-native';
const InputComponent = (props)=>{
return(
<TextInput
style={{height: 40, backgroundColor:'white'}}
placeholder="add the item in to do list"
onChangeText={newText => props.onchangeValue(newText)}
/>
)
}
export default InputComponent;
You must use arrow-functions in the onPress method of your buttonComponent like this:
onPress={()=>props.addItem(...)}
I am developing an e-commerce application using React Native and I am trying to use useState in the drawerContent and it tells me this
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
Thank you in advance for your answers.
Here's the code
import React, { useState } from 'react'
import { View, Text, TouchableOpacity, FlatList, StyleSheet, StatusBar } from 'react-native'
import IonIcons from "react-native-vector-icons/Ionicons"
import { categories } from '../../../services/DataTest'
import DrawerSearch from './DrawerSearch'
import DrawerItem from './DrawerItem'
export default function DrawerContent (props) {
const [search, setSearch] = useState("");
return (
<View>
<TouchableOpacity
style={styles.customDrawerTouch}
>
<View style={styles.backButtonRow}>
<IonIcons
name="ios-arrow-back"
size={25}
style={styles.customDrawerIcon}
color="#666666"
/>
<Text style={{ color: '#666666' }}>Back to Components</Text>
</View>
</TouchableOpacity>
<DrawerSearch value={search} setValue={setSearch}/>
<FlatList
data={categories}
keyExtractor={(item, index) => index.toString()}
renderItem={DrawerItem}
/>
</View>
);
}
const styles = StyleSheet.create({
customDrawerTouch: {
marginTop: StatusBar.currentHeight,
paddingLeft: 13,
paddingTop: 15,
},
customDrawerIcon: {
paddingRight: 10
},
backButtonRow: {
flexDirection: 'row',
alignItems: 'center',
paddingBottom: 17,
paddingLeft: 3,
borderBottomColor: '#F0F0F0',
borderBottomWidth: 1,
},
});
I'm using this component here
import * as React from 'react';
import { View, StyleSheet, StatusBar } from 'react-native';
import { createDrawerNavigator } from '#react-navigation/drawer';
import HeaderCategorie from '../../components/categories/index/HeaderCategorie';
import SearchBar from '../../components/home/index/SearchBar';
import DrawerContent from '../../components/categories/index/DrawerContent';
const Drawer = createDrawerNavigator();
function CategoriesScreen({ navigation }) {
return (
<View style={styles.container}>
<HeaderCategorie navigation={navigation}/>
<View style={styles.headerSearch}>
<SearchBar />
</View>
</View>
)
}
export default function Categories() {
return (
<Drawer.Navigator initialRouteName="Categories"
drawerContent={DrawerContent}
screenOptions={{headerShown:false}}
>
<Drawer.Screen name="Categories" component={CategoriesScreen} />
</Drawer.Navigator>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: "flex-start",
alignItems: "center",
marginTop: StatusBar.currentHeight,
},
headerSearch: {
marginVertical:10
},
headerSearchText: {
fontWeight:"bold",
fontSize:35,
marginLeft:20,
marginVertical:15,
}
});
Reason: By using drawerContent={DrawerContent}, you are actually passing the reference of the DrawerContent function, which ends up breaking rules of hooks.
So to resolve this, change the following line:
<Drawer.Navigator initialRouteName="Categories"
drawerContent={DrawerContent}
screenOptions={{headerShown:false}}
>
to this
<Drawer.Navigator initialRouteName="Categories"
drawerContent={(props)=> <DrawerContent {...props}/>} // here
screenOptions={{headerShown:false}}
>
demo snack
I'm developing a react native app with redux as a state management and trying the following implementation:
Fetching data from Server (Firebase) before rendering the app. I have a loading screen, which is working fine, but i cant dispatch my function in it for fetching the data from server and write directly to the current state. I dont see that the state is changed, but when I saving the code (as it is) again the state is updated as I expected. So i think my code is fetching the data after the first rendering is done.
I cant figure out the the problem. Cause i put my code for dispatching in the "useeffect" hook as i should or not?
import React, {useEffect} from 'react';
import {ActivityIndicator, View} from 'react-native';
import {Images, useTheme} from '#config';
import {Image, Text} from '#components';
import styles from './styles';
import {ApplicationActions} from '#actions';
import { store } from '/Users/user1/KitaList/app/store/index.js'
export default function Loading({navigation}) {
const {colors} = useTheme();
const onProcess = () => {
setTimeout(() => {
navigation.replace('Main');
}, 2500);
};
useEffect(() => {
store.dispatch(ApplicationActions.ongetKitadata()); //Executing dispatchting getting data
onProcess();
}, []);
return (
<View style={styles.container}>
<View style={{alignItems: 'center'}}>
<Image source={Images.logo} style={styles.logo} resizeMode="contain" />
<Text title1 style={{marginTop: 10}}>
MyApp
</Text>
<Text headline primaryColor style={{marginTop: 10}}>
MyApp DIRECTORY
</Text>
</View>
<ActivityIndicator
size="large"
color={colors.text}
style={{
position: 'absolute',
top: 260,
left: 0,
right: 0,
bottom: 0,
justifyContent: 'center',
alignItems: 'center',
}}
/>
</View>
);
}
I am trying to clean up my styles by using a StyleSheet, but I can't seem to get it to work. I believe the error (seen below) is caused when I attempt to create a StyleSheet (const styles = EStyleSheet.create.
Note I am using react-native-extended-stylesheet However this is not the problem. This also happens with react-native's stylesheet.
This a picture of the error:
This this my code:
import React, { Component } from "react";
import {
View,
Text,
Button,
Image,
StyleSheet,
TextInput,
KeyboardAvoidingView,
TouchableOpacity
} from "react-native";
export default class Login extends Component {
render() {
return (
<View style={styles.wrapper}>
<Text>Login screen </Text>
<KeyboardAvoidingView behavior="padding" style={styles.loginContainer}>
<TextInput
placeholder="username or email"
placeholderTextColor='whitesmoke'
style={styles.input}
/>
<TextInput
placeholder="password"
secureTextEntry
placeholderTextColor='whitesmoke'
style={styles.input}
/>
<TouchableOpacity style={styles.loginbutton} onPress={() => this.props.navigation.navigate("Grades")}>
<Text style={{
textAlign: 'center',
color: "whitesmoke",
fontWeight: '700',
}}>
Login
</Text>
</TouchableOpacity>
</KeyboardAvoidingView>
</View>
);
}
}
const styles = StyleSheet.create({
loginContainer: {
paddingHorizontal: 9,
backgroundColor: "red"
},
input: {
paddingHorizontal: 10,
marginBottom: 10,
color: '#f1c40f', //sunflower color
backgroundColor: '#3498db',
},
logo: {
width: 231,
height: 231
},
wrapper: {
flex: 1,
alignItems: "center",
justifyContent: "center"
}
});
Here is my app.js.
import React from "react";
import { Font } from "expo";
import { Root } from "./app/router";
import { FontError } from "./app/components/fontError";
export default class App extends React.Component {
state = {
fontLoaded: false
};
async componentDidMount() {
await Font.loadAsync({
Arial: require("./app/resources/Arial.ttf")
});
this.setState({ fontLoaded: true });
}
render() {
if (!this.state.fontLoaded) return <FontError/>;
return <Root />;
}
// ...
}
My root component is router.js, I am using react-navigation.
import React, { Component } from "react";
import { createStackNavigator } from "react-navigation";
import {
Login,
Grades,
} from "./screens";
export const Root = createStackNavigator({
Login: {screen: Login},
Grades: {screen: Grades},
});
Feel free to ask me to append any additional information.
Thanks for your help in advance.
To fix my error I just re-cloned the repo and added back in all the code I wrote.
Thankfully I didn't push this error to the master branch.
This fixed the error.
*note in the process I got rid off react-native-extended-stylesheet, so it might have been cause of error.
I am trying to add a stateless component to my button.
const button = ({onButtonPress, buttonText}) => {
return (
<TouchableHighlight
onPress={() => onButtonPress()}>
<ButtonContent text={buttonText}/>
</TouchableHighlight>
)
};
and get this error:
Warning: Stateless function components cannot be given refs (See ref "childRef"
in StatelessComponent created by TouchableHighlight).
Attempts to access this ref will fail.
I have read up on the issue but I am still new to javascript and RN and have not found a solution. Any help would be appreciated.
full code:
GlossaryButtonContent:
import React from 'react';
import {
View,
Text,
Image,
StyleSheet
} from 'react-native';
import Colours from '../constants/Colours';
import {
arrowForwardDark,
starDarkFill
} from '../assets/icons';
type Props = {
text: string,
showFavButton?: boolean
}
export default ({text, showFavButton} : Props) => {
return (
<View style={styles.container}>
{showFavButton &&
<Image
style={styles.star}
source={starDarkFill}/>}
<Text style={[styles.text, showFavButton && styles.favButton]}>
{showFavButton ? 'Favourites' : text}
</Text>
<Image
style={styles.image}
source={arrowForwardDark}
opacity={showFavButton ? .5 : 1}/>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'row',
alignItems: 'center'
},
favButton: {
marginLeft: 10,
color: Colours.darkTextHalf
},
text: {
flex: 1,
paddingTop: 5,
marginLeft: 20,
fontFamily: 'Bariol-Bold',
fontSize: 24,
color: Colours.darkText
},
image: {
marginRight: 20
},
star: {
marginLeft: 10
}
});
GlossaryButton:
import React from 'react';
import {
TouchableHighlight,
StyleSheet
} from 'react-native';
import Colours from '../constants/Colours';
import ShadowedBox from './ShadowedBox';
import GlossaryButtonContent from './GlossaryButtonContent';
type Props = {
buttonText: string,
onButtonPress: Function,
rowID: number,
sectionID?: string,
showFavButton?: boolean
}
export default ({buttonText, onButtonPress, rowID, sectionID, showFavButton} : Props) => {
return (
<ShadowedBox
style={styles.container}
backColor={showFavButton && Colours.yellow}>
<TouchableHighlight
style={styles.button}
underlayColor={Colours.green}
onPress={() => onButtonPress(rowID, sectionID)}>
<GlossaryButtonContent
text={buttonText}
showFavButton={showFavButton}/>
</TouchableHighlight>
</ShadowedBox>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
height: 60,
marginBottom: 10,
borderRadius: 5
},
button: {
flex: 1,
borderRadius: 5
}
});
Basically, Stateless components cannot have refs.
So, having a stateless component in the middle of the render tree will create a void in the ref chain, meaning you cannot access lower-down components.
So, the problem comes from trying to do this:
let Stateless = (props) => (
<div />
);
let Wrapper = React.createClass({
render() {
return <Stateless ref="stateeee" />
}
});
TouchableHighlight needs to give a ref to its child. And this triggers that warning.
Answer:
You can't actually make a stateless component a child of TouchableHighlight
Solution:
Use createClass or class to create the child of TouchableHighlight, that is GlossaryButtonContent.
See this github issue for more info and this one