React native using class components error - react-native

I am just getting started with React native and I came across a rather unexpected bug. Consider the code below
export default class RecipePage extends Component {
state = {
ingredients: ["apple", "orange"]
}
render() {
return (
<View>
<ShowRecipes ingredients={this.state.ingredients} />
</View>
)
}
}
class ShowRecipes extends Component {
render() {
return (
<View>
<Text>This is inside ShowRecipes</Text>
</View>
)
}
}
export default ShowRecipes
I get an error below which points to <ShowRecipes ingredients={this.state.ingredients} />
"TypeError: undefined is not an object"
I am getting this error and I am not able to figure out what's causing it. Can someone please help fix this mistake.
Any help is appreciated.

You should put State in the contructor to get like this this.state.something
Try this code.
export default class RecipePage extends Component {
constructor(props) {
super(props)
this.state = {
ingredients: ["apple", "orange"]
}
}
}

Related

react-native window.setInterval, trying to display an incrimenting number

I want to display a number that increases once every second, rather than using some kind of time function I am using window.setInterval because eventually I will replace this with some more complicated code that instead of just displaying the number calls some function and displays the result. Here is the code I have right now:
export default class Test extends Component {
constructor(props){
super(props)
this.state = {counter:0}
}
render(){
newCounter = this.state.counter+1 // I am going to replace this
// with something like:
// newCounter = someFunc()
func = this.setState
window.setInterval(function(){
func({counter:newCounter})
},1000);
return(
<View>
<Text>{this.state.counter}</Text>
</View>
)
}
}
It gives me this error: undefined is not an object (evaluating 'this.updater')
how can I do this correctly? Thanks
Try this:
export default class Test extends Component {
constructor(props){
super(props)
this.state = {counter:0}
}
componentDidMount(){
setInterval(() => {
this.setState( prevState => ({counter: prevState.counter + 1}));
},1000);
}
render(){
return(
<View>
<Text>{this.state.counter}</Text>
</View>
)
}
}
Basically, you want to use the function arrow with set Interval, to not lose the context of the this keyword, and try to use set State outside of the render method.
Here is a demo as well: https://snack.expo.io/HkikISZMm

React native: how can i pass value in my custom component

i want to pass my params value in my custom component so below is my code
Header.js
class Header extends Component {
constructor(props) {
super(props);
}
render() {
return (
<View >
<Text >Title</Text>
<Text>subtitle</Text>
</View>
);
}
}
I call my Header.js from my main.js
class Main extends Component {
constructor(props) {
super(props);
}
render() {
return (
<Header title = {this.props.navigation.state.params.screen_title} subtitle= {this.props.navigation.state.params.subtitle} />
);
}
}
I pass my title and subtitle in my header component , i just wanted to know how can i access my passing variable value in my header component ? your all suggestions are appreciable
Its very simple You can access it by
this.props.title
this.props.subTitle
this.props.nameOfTheProps

invariant violation element type is invalid

Guys I need to define a simple component in RN, but I keep getting this error:
enter image description here
and this is my simple component code:
export default class Welcome extends Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
and the way I import it into my page(Intro.js):
export default class App extends Component<{}> {
render() {
return (
<Welcome name="Sara" />
);
}
}
Finally I call the page including the component(Intro.js) in my app.js like this:
import { Intro } from './app/screens/Intro.js';
export default class App extends Component {
render(){
return(
<Intro />
)
}
}
version I'm using:
react-native-cli: 2.0.1
react-native: 0.49.3
Appreciate your answers
As i can see in your code
export default class Welcome extends Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
You had use which is html tag not a react natine element or component.
So this may be the reason for the error.
You can use this code.
export default class Welcome extends Component {
render() {
return <Text>Hello, {this.props.name}</Text>;
}
}

How to get Element Properties in React Native on a Click Event

How should I access the properties of an element without using the 'this' keyword in React Native? I have a function with which the parent class itself is bound as 'this' but I want to access the properties of the element that is being clicked. Here's the code-
import {Circle} from 'react-native-svg';
export default App extends Component {
constructor(props) {
super(props);
this.state = {activeX: null}
}
handleTouch(event) {
const x = event.target.cx; //How to access "cx" property here?
this.setState({ activeX: x });
}
render() {
return (
<Circle cx='10' cy='10' r='5' onPress={this.handleTouch.bind(this)}/>
<Circle cx='20' cy='20' r='5' onPress={this.handleTouch.bind(this)}/>
);
}
}
Try this
import {Circle} from 'react-native-svg';
export default App extends Component {
constructor(props) {
super(props);
this.state = {
activeX: null,
cx: 10
}
}
handleTouch = () => {
const x = this.state.cx
this.setState({ activeX: x });
}
render() {
return (
<Circle cx={this.state.cx} cy='10' r='5' onPress={this.handleTouch}/>
);
}
}
import ReactNativeComponentTree from'react-native/Libraries/Renderer/src/renderers/native/ReactNativeComponentTree';
And access the properties as-
const x = ReactNativeComponentTree.getInstanceFromNode(event.currentTarget)._currentElement.props.cx;
Sorry for leaving an answer but I cannot leave a comment since <50 rep.
You should edit the improve part of your answer, with the following bit:
import ReactNativeComponentTree from 'react-native';
instead of what you have right now,
import ReactNativeComponentTree from'react-native/Libraries/Renderer/src/renderers/native/ReactNativeComponentTree';
since is throwing an error (trying to import unknown module).
A better way of accessing the component properties in an event is actually by creating a component and passing it the needed data:
import { Circle } from 'react-native-svg';
class TouchableCircle extends React.PureComponent {
constructor(props) {
super(props);
this.circlePressed = this.circlePressed.bind(this);
}
circlePressed(){
this.props.onPress(this.props.cx);
}
render() {
return (
<Circle cx={this.props.cx} cy={this.props.cy} r={this.props.r} onPress={this.circlePressed}/>
);
}
}
export default App extends Component {
constructor(props) {
super(props);
this.state = {activeX: null}
this.handleTouch = this.handleTouch.bind(this);
}
handleTouch(cx) {
this.setState({ activeX: cx });
}
render() {
return (
<TouchableCircle cx='10' cy='10' r='5' onPress={this.handleTouch}/>
<TouchableCircle cx='20' cy='20' r='5' onPress={this.handleTouch}/>
);
}
}
NB: Performance tip from Facebook for event handlers:
We generally recommend binding in the constructor or using the property initializer syntax, to avoid this sort of performance problem. (i.e. to avoid the creation of the callback everytime a component renders)
ref: React Handling Events
(credits to https://stackoverflow.com/a/42125039/1152843)
You can change your event handler to a curried function like so:
import {Circle} from 'react-native-svg';
export default App extends Component {
constructor(props) {
super(props);
this.state = {activeX: null}
}
//Use ES6 arrow and avoid this.bind
//Curried function handleTouch accepts cx, cy as extra parameters
handleTouch = (cx, cy) => event => {
console.log(cx, cy) // This is how you access props passed to Circle here
console.log(event)
this.setState({ activeX: cx });
}
render() {
//You are actually invoking the handleTouch function here, whose return value is
//a function, which is set as the onPress event handler for the <Circle> component
return (
<Circle cx='10' cy='10' r='5' onPress={this.handleTouch(10, 10)}/>
<Circle cx='20' cy='20' r='5' onPress={this.handleTouch.(20, 20)}/>
);
}
}
Checkout the working snack below:
https://snack.expo.io/#prashand/accessing-props-from-react-native-touch-event

How to call a function from another class in React-Native?

I am working on React-Native, i want to call a function from different class but when i am trying to do it's showing some error.
Class A
import B from './B.js';
class A extends Component {
_onItemPressed(item){
B.abc();
}
render() {
return (
<TouchableHighlight
underlayColor={Colors.colors.lightgrey}
style={{padding: 15}}
onPress={this._onItemPressed.bind(this)}>
<Text>Click Me !</Text>
</TouchableHighlight>
);
}
}
Class B
class B extends Component {
abc(){
alert('Hello World');
}
render() {
return (
<View>
<Text>Welcome to React Native</Text>
</View>
);
}
}
But error message is coming after pressing the button in Class A, 'undefined is not a function (evaluating 'B.default._abc()')'
Please kindly go through my post and suggest me some solution.
Thanks
You have two options, either to use an object or use class name, let's start with object
class B {
abc() {
alert("Hello World");
}
}
const b = new B();
export default b;
So when you call this file you can access the function abc like the following
import b from './B.js';
class A extends Component {
_onItemPressed(item){
b.abc();
}
...
The other way is to use class instead as follow
class B{}
B.abc = function(){
alert("Hello World");
}
module.exports = {
functions: B
};
So when you call this file you can access the function abc like the following
import b from './B.js';
class A extends Component {
_onItemPressed(item){
b.functions.abc();
}
...
Note: B class should not be a component, you can use it as a helper class.
also, you can enhance the way you deal with the object using singleton pattern as I already mention in
React native- Best way to create singleton pattern
UPDATE: If you insist to use component instead of a class function, you can call it through reference, as follows:
export default class B extends Component {
constructor(props) {
super(props);
this.abc = this.abc.bind(this);
}
abc(){
alert('Hello World');
}
render() {
return null
}
}
now in A component you can call B by reference
import B from "./B.js";
class A extends Component {
_onItemPressed(item) {
this._b.abc();
}
render() {
return (
<TouchableHighlight
underlayColor={Colors.colors.lightgrey}
style={{ padding: 15 }}
onPress={this._onItemPressed.bind(this)}
>
<Text>Click Me !</Text>
<B ref={ref => (this._b = ref)} />
</TouchableHighlight>
);
}
}
You dont initiate your class, to solve this you need to change the B.abc() to new B().abc();
I noticed you didn't export your class B. Try
class B extends Component {
static abc(){
alert('Hello World');
}}
export default B
then import it in class A
import B from './B';
Let me know if this worked for you.
You have to create the parent with a constructor, access to super method for extend well the Component Class, then export the parent class and extend it on the Class A where you have access to this functions by this context of the class
export default class B extends Component {
constructor(props){
super(props);
}
abc(){
alert('Hello World');
}
render() {
return (
<View>
<Text>Welcome to React Native</Text>
</View>
);
}
}
import B from './B.js';
export default class A extends B {
_onItemPressed(item){
this.abc();
}
render() {
return (
<TouchableHighlight
underlayColor={Colors.colors.lightgrey}
style={{padding: 15}}
onPress={this._onItemPressed.bind(this)}>
<Text>Click Me !</Text>
</TouchableHighlight>
);
}
}
I tried various solutions on this page but that didn't work. I am copying a solution from another web page here. Very simple and impressive. Might help someone looking for a simple solution:
How to Call Another Class Function From Default Class in React Native
Here is the complete example code:
import { StyleSheet, View, Alert, Platform, Button } from 'react-native';
export default class MyProject extends Component {
constructor(props) {
super(props)
Obj = new Second();
}
CallFunction_1=()=>{
Obj.SecondClassFunction() ;
}
CallFunction_2=()=>{
Obj.SecondClassFunctionWithArgument("Hello Text");
}
render() {
return (
<View style={styles.MainContainer}>
<View style={{margin: 10}}>
<Button title="Call Another Class Function Without Argument" onPress={this.CallFunction_1} />
</View>
<View style={{margin: 10}}>
<Button title="Call Another Class Function With Argument" onPress={this.CallFunction_2} />
</View>
</View>
);
}
}
class Second extends Component {
SecondClassFunction=()=>{
Alert.alert("Second Class Function Without Argument Called");
}
SecondClassFunctionWithArgument=(Value)=>{
Alert.alert(Value);
}
}
const styles = StyleSheet.create(
{
MainContainer: {
justifyContent: 'center',
alignItems: 'center',
flex: 1,
backgroundColor: '#F5FCFF',
paddingTop: (Platform.OS) === 'ios' ? 20 : 0
}
});
I can see that you are not exporting the class B, you are only importing. Please try adding an export statement at bottom of the class B file like so export default B.
Hope this helps
Make abc function static and export B class.
export default class B extends Component {
static abc(){
alert('Hello World');
}
}
Import the first class in the another class where you want to use the function defined in first class. In this case, We are using a function defined in class1 to class2.
export default class class1 extends React.Component{
constructor(props)
{
...
}
static function(){
...
}
}
**Now import it to another class i:e; class2**
import class1 from 'class1';
export default class class2 extends React.Component{
componentWillMount()
{
class1.function();
}
}