Proper way of defining/initializing state in reactjs or react-native - reactjs

So far I understand there are two ways to define state in react class.
The first as many people use them, is as follows:
import React, { Component } from "react";
import { View, Text } from "react-native";
export default class Test extends Component {
constructor (props) {
super(props)
this.state = {
text: 'hello'
}
}
render() {
return (
<View>
<Text>{this.state.text}</Text>
</View>
);
}
}
The second one is as follows:
import React, { Component } from "react";
import { View, Text } from "react-native";
export default class Test extends Component {
state = {
text: "hello"
}
render() {
return (
<View>
<Text>{this.state.text}</Text>
</View>
);
}
}
The difference is at using constructor or not. What is the effect and is there any difference at all between the two? If there is, which one should I use?
Thank you!

Both methods are correct. Make sure you have support for class properties enabled in the babelrc. If you are using CRA both will work. Constructor one is better on the eyes if you want to seed the initial state from props.

Both methods are fine. Second one is the short-hand method

Related

Navigation inside class component not working

While using class component I cannot use navigation its telling invalid hooks . How can I use navigation inside class component?
this is what i am trying to acheive , navigation option inside class component. actually i a m newbie .Can anyone help me?
import React, { Component } from 'react';
import { Text ,View ,TouchableOpacity } from 'react-native';
import { useNavigation } from '#react-navigation/native';
class Mpin extends Component {
const navigation= useNavigation();
render() {
return (
<Text>....</Text>
<TouchableOpacity onPress={()=>navigation.navigate('LoginPage')}>
<Text>SetMPIN</Text>
</TouchableOpacity>
);
}
}
export default Mpin;
You cannot use hooks inside class component. Inside class component you can directly access navigation object from props.
this.props.navigation.navigate('LoginPage')
Actually I can understand what you are trying to say. I came through this same kind of mistakes when I first started.
Use the below functional component inside of your class component like shown . By doing so you can access navigation inside class component.
import React, { Component } from 'react';
import { Text ,View ,TouchableOpacity } from 'react-native';
import { useNavigation } from '#react-navigation/native';
function ForgotMpin() {
const navigation = useNavigation();
return (
<View>
<TouchableOpacity
style={...}
onPress={() => navigation.navigate("ForgotPin")}
>
<Text>... </Text>
</TouchableOpacity>
</View>
);
}
class Mpin extends Component {
render() {
return (
<Text>....</Text>
<ForgotMpin screenName="forgotMpin" />
);
}
}
export default Mpin;
you can use vanilla js in those cases, the following code helps you redirect or navigate to other paths:
window.locate.replace('/pathname')
if you want to use Navigate or useNavigate you will have to convert to function component and not a class component

Simplify this repeating code pattern on class components

I'm currently implementing accessibility (VoiceOver/Talkback) support for my application, and I use AccessibilityInfo.setAccessibilityFocus (see official docs) quite a lot which requires a reactTag, which I can only get by using findNodeHandle as per this answer.
This means that I keep repeating the same pattern involving quite a few function calls, over and over on many different components. I originally tried to move the stored references and the call to set focus to my state manager (using MobX in this case) but I ended up getting a lot of failed findNodeHandle calls because sometime the component had unmounted before the call was made.
This is the gist of what I keep repeating:
import React, {Component} from 'react'
import {
...
findNodeHandle,
AccessibilityInfo
...
} from 'react-native';
class Sample extends React.Component {
constructor(props) {
super(props)
this.accessibilityRef = null;
}
...
componentDidMount() {
this.setAccessibilityFocus()
}
componentDidUpdate() {
this.setAccessibilityFocus()
}
setAccessibilityRef(el) {
this.accessibilityRef = el
}
setAccessibilityFocus() {
if (this.accessibilityRef) {
const reactTag = findNodeHandle(this.accessibilityRef);
AccessibilityInfo.setAccessibilityFocus(reactTag);
}
}
render() {
return (
<View ref={this.setAccessibilityRef} accessible={true}>
...
</View>
)
}
}
Would it be possible to somehow make something reusable out of this? Maybe a decorator or as a class extension so that I can reuse it?
Yes, you can...
Let, SampleWrapper.js is your wrapper.
import React, {Component} from 'react'
import {
...
findNodeHandle,
AccessibilityInfo
...
} from 'react-native';
export default class SampleWrapper extends Component {
constructor(props) {
super(props)
this.accessibilityRef = null;
}
...
componentDidMount() {
this.setAccessibilityFocus()
}
componentDidUpdate() {
this.setAccessibilityFocus()
}
setAccessibilityRef(el) {
this.accessibilityRef = el
}
setAccessibilityFocus() {
if (this.accessibilityRef) {
const reactTag = findNodeHandle(this.accessibilityRef);
AccessibilityInfo.setAccessibilityFocus(reactTag);
}
}
render() {
return (
<View ref={this.setAccessibilityRef} accessible={true}>
{this.props.children}
</View>
)
}
}
Now, assume you want to use the above wrapper in your Sample.js
import React, {Component} from 'react'
import SampleWrapper from './path/to/SampleWrapper'
class Sample extends Component {
constructor(props) {
super(props)
}
render() {
return (
<SampleWrapper>
....
</SampleWrapper>
)
}
}
You can put ref s and then you can control it as you expect.
PS: I didn't test this before posting. Hope this will work and help you. If you have any problems regarding this answer or if you want to add something more and you have doubts about how to do it, please just comment on it here.

How to get data from next screen using textInput on to a previous screen which use only Text field in react native

This is my code . Its just a simple testing screen. Navigation is done on both screens. Im beginner so im not familiar with redux. I want that when the user input the text on second screen the same text will appear on first screen as User Name when user switch to go back from second to first screen. Kindly help me. Thanks.
import React, { Component } from 'react';
import { View, Text } from 'react-native';
class FirstScreen extends Component {
constructor(props) {
super(props);
this.state = {
};
}
render() {
return (
<View>
<Text> UserNAme </Text>
</View>
);
}
}
export default FirstScreen;
import React, { Component } from 'react';
import {View, TextInput} from 'react-native';
class SecondScreen extends Component {
constructor(props) {
super(props);
this.state = {
};
}
render() {
return (
<View>
<TextInput/>
</View>
);
}
}
export default SecondScreen;
You can use a service file, PubSub (https://www.npmjs.com/package/pubsub-js) or you can store the value in the local store in the second screen and retrieve in the first screen.
Store value in a local store as below:
try {
await AsyncStorage.setItem(
key,
value
)
} catch (error) {
}
Retrieve value :
try {
return await AsyncStorage.getItem(key)
} catch (error) {
}
Since you are not using any global store/state, therefore to pass the value to the previous screen you can pass it as a param while navigating to previous screen and use it there.
But if you have the requirement of using a value on multiple screens, you should use a global state/store. (you can use mobx as it is easy to learn and can be used for small applications)
Hope this helps...
There are 2 ways to solve this:
Using Redux. Redux gives you ability to save data and access it in any screen.
You can pass a callback function to next screen and call it in second screen before pop function.
import React, { Component } from 'react';
import { View, Text } from 'react-native';
class FirstScreen extends Component {
constructor(props) {
super(props);
this.state = {
username: '',
};
}
render() {
return (
<View>
<Text>{this.state.username}</Text>
</View>
);
}
callback(username) {
this.setState({ username });
}
goToSecondScreen() {
// Depends on your navigation library
navigation.push('SecondScreen', {
callback: this.callback,
});
}
}
export default FirstScreen;
import React, { Component } from 'react';
import { View, TextInput } from 'react-native';
class SecondScreen extends Component {
constructor(props) {
super(props);
this.state = {
text: '',
};
}
render() {
return (
<View>
<TextInput onChangeText={this.onChangeText} />
</View>
);
}
onChangeText(text) {
this.setState({ text });
}
goBack() {
this.props.callback && this.props.callback(this.state.text);
navigation.pop();
}
}
export default SecondScreen;
The best way to do this is using redux. Redux allows you to manage all of the states in one place. Async storage is also an option but it is not recommended. If you use react navigation, the best way to do is pass the data to next screen like this.
navigation.navigate('SecondScreen', { myText: 'My text' });
You can change 'My Text' to your state variable.
And on the next screen, you access the data using
navigation.getParam('myText') //exact name of the key that was passed in previous screen.
This would return you the value that was passed in previous screen
1) by using state we can transfer data one component to another component
this.setState({
userName: val.userName,
userId: val.userId
});
https://facebook.github.io/react-native/docs/state
2) Window localStorage Property
by using localStorage in javascript we can store item and get for where you want
https://www.w3schools.com/jsref/prop_win_localstorage.asp

How to access state of one component into another component in react

import React, { Component } from 'react';
class one extends React.Component
{
constructor()
{
super();
this.state = {
number:26
}
}
render()
{
return(
<div></div>
);
}
}
export default one;
import React, { Component } from 'react';
import one from './one'
class HomePage extends React.Component
{
render()
{
return(
<div>{one.state.number}</div>
);
}
}
export default HomePage;
is it possible to access number state
is there any way to access state of one component into another component?
please suggest me if any solution is present.
As Shubam has explained it, Though I would like to form it as a complete answer
First of all, I would like to let you know that Never Use lowercase letters to name your React Components.So name your component to One instead of one.
Now Comming back to your question:-
No This is not Possible, If your app contains few components then it's better to pass the state object as the props, But if your app contains too many components then better to use predictable state containers like Redux or Flux rather than passing state as props.
So you may apply these changes and I hope You will get What You Desire:-
One Component:-
import React, { Component } from 'react';
import Homepage from './homepage';
class One extends React.Component
{
constructor()
{
super();
this.state = {
number:26
}
}
render()
{
return(
<Homepage data={this.state}/>
);
}
}
export default One;
Homepage Component:-
import React, { Component } from 'react';
class Homepage extends React.Component
{
render()
{
console.log("this is homepage",this.props);
return(
<div>{this.props.data.number}</div>
);
}
}
export default Homepage;
Please Raise Your doubts if any, Or if you find any error in it.

Click event in ReactJS error: imports/ui/ParentComponent.jsx:5:16: Unexpected token (5:16)

I am trying to learn Event in ReactJS.
I created 2 components
ChildComponent is
import React, { Component } from 'react';
// App component - represents the whole app
export default class ChildComponent extends Component {
render() {
return (
<button onClick={this.props.onBannerClick}>Click me!</button>
);
}
}
And ParentComponent is
import React, { Component } from 'react';
import ChildComponent from './ChildComponent.jsx'
// App component - represents the whole app
export default class ParentComponent extends Component {
performMagic: function() {
alert('TAADAH!');
},
render() {
return (
<BannerAd onBannerClick={this.performMagic} />
);
}
}
but I got the error
Errors prevented startup:
While building for web.browser:
imports/ui/ParentComponent.jsx:5:16: Unexpected token (5:16)
Your application has errors. Waiting for file change.
I think the error is from
performMagic: function() {
alert('TAADAH!');
},
But I do know what the error is.
By the way, can anybody recommends me good debug tools for ReactJS?
Because you're using the ES6 syntax you'll have to bind the function to the instance using the following approach.
constructor(props) {
super(props)
this.performMagic = this.performMagic.bind(this)
}
This will allow you to use the this keyword in the onClick call
import React, { Component } from 'react';
import ChildComponent from './ChildComponent.jsx'
// App component - represents the whole app
export default class ParentComponent extends Component {
constructor(props) {
super(props)
this.performMagic = this.performMagic.bind(this)
}
performMagic() {
alert('TAADAH!');
}
render() {
return (
<BannerAd onBannerClick={this.performMagic} />
);
}
}
Need to write:
performMagic () {
alert('TAADAH!');
},
You need to use new sintax for functions, when write class which is new sintax.
EDIT: You can use "React Developer Tools" chrome extension and gaearon "redux-devtools" for development.
You need to use the new ES6 syntax when making your React Component a class. Use
performMagic() {
alert('TAADAH!');
}
make sure you don't put a comma after the function

Resources