React native set state is not working - reactjs

I am trying to update state in react native component.
But its getting errors, Could someone help me.
I'm using react-native-cli verions: 2.0.1
react-native verions: 0.55.4
Here is my code:
import React, { Component } from 'react'
import {
Button,
Text,
View,
} from 'react-native';
export class ToggleButton extends Component {
state = {
isDone: false
};
onAction() {
const value = !this.state.isDone;
this.setState({ isDone: value });
const newValue = this.state.isDone;
console.log(newValue);
}
render() {
return (
<View>
<Button
title="Action"
onPress={this.onAction}
/>
</View>
)
}
}
export default ToggleButton;

You have three different solutions.
Bind your function in the constructor.
Use the experimental public class fields syntax.
Pass a lambda to executing your function.
The problem is that you're loosing the reference to this, because the function is not executed in the original context, so this.setState is not a function, but a undefined.
In this page there are examples for all of the approaches: https://reactjs.org/docs/handling-events.html

Change
onPress={this.onAction}
to
onPress={this.onAction.bind(this)}
Check: this

Below is the solution
import React, { Component } from 'react'
import {
Button,
Text,
View,
} from 'react-native';
export class ToggleButton extends Component {
// Add state in constructor like this
constructor(props){
super(props);
this.state = {
isDone: false
};
}
onAction() {
const value = !this.state.isDone;
this.setState({ isDone: value });
const newValue = this.state.isDone;
console.log(newValue);
}
render() {
return (
<View>
<Button
title="Action"
// Add function with onPress
onPress={() => this.onAction}
/>
</View>
)
}
}
export default ToggleButton;

Related

React Native - render a component onClick on an Icon

A part of my app has an 'icon'. When I 'click' on the icon, the State of the parent component changes to 'true' and I want a new 'Component' to render saying 'I am a new Component'. I am trying like this below, there is no error showing at the debugger. The Icon is an image component that I am importing. Here is the Code.
This is the parent Component
import React, {Component} from 'react';
import {View} from 'react-native';
import {Icon} from '../ui/Icon';
type HomeSceneState = {
calendarState:boolean
}
class HomeScene extends Component<HomeSceneState> {
state = {
calendarState:false
}
openCalendar = () => {
console.log("open calendar")
this.setState({
calendarState : true
})
}
render() {
return (
<View style={{marginBottom: spacing.double,
backgroundColor:"black", flexDirection:"row"
}}>
<View>
<Icon onPress = {() => this.openCalendar()} />
{this.calendarState ? <Casie/> : null }
</View>
</View>
);
}
}
export default HomeScene;
The Children Component looks like below
class Casie extends Component<CalendarProps> {
render() {
return (
<View>
I am a new Component
</View>
);
}
}
export default Casie;
replace <Calendar/> by your child component name <Casie/> (in your case). It seems you are not rendering your child component when the state changes.
In your parent component you import the react native navigation.
after you can use useNavigation for navigate the page. Sorry my english.
import { useNavigation } from '#react-navigation/native'
class HomeScene extends Component<HomeSceneState> {
state = {
calendarState:false
}
openCalendar = () => {
console.log("open calendar")
navigation.navigate('Casie')
}
render() {
return (...)
}
}
export default HomeScene;

how to pass state using navigator in react native navigator

I want to pass a state using react navigator. I want to pass showing: false, so my progress bar component will disappear.Can someone please explain how I can do this. Thanks so much.
Here is my code.
import React, { Component } from "react";
import { Button, View, Text, TextInput } from "react-native";
import ContinueButton from "./ContinueButton";
import { CreateAboutMe } from "./StyleSheet/AboutMeStyle";
import * as Progress from "react-native-progress";
export class AboutUser extends Component {
constructor(props) {
super(props);
this.navigatToInterests = this.navigatToInterests.bind(this);
this.checkEntry = this.checkEntry.bind(this);
this.state = {
value: "",
showing: true,
};
}
navigatToInterests = ({ navigation }) => {
let checkDescription = this.state.value;
if (checkDescription === "") {
alert("Please tell people about yourself");
} else {
this.props.navigation.navigate("Interests");
}
};
checkEntry = (Description, value) => {
this.setState({ value: value });
console.log(this.state.value);
};
render() {
return (
<View style={CreateAboutMe.overAllContainer}>
{this.state.showing && (
<Progress.Bar
progress={0.7667}
width={300}
color={"red"}
style={CreateAboutMe.progressbar}
showing={this.state.showing}
/>
)}
Which version of React Navigation are you using?
In version 4, you can send some data using the second argument of the navigate function like this:
this.props.navigation.navigate("Interests",{"someKey":"someValue", ...});
Then you can grab the data in the next page through the props:
let someValue = this.props.navigation.getParam('someKey');

what is best way to get props in React / React Native

I'm really regarding props in React/React-Native. I have a parent view. In this view I'm getting the user data from a LocalStorage.['
import React, { Component } from 'react';
import { Container, Content, View } from 'native-base';
import NutrionalToolbar from '../../components/NutrionalToolbar';
import { AsyncStorage } from 'react-native';
export default class LogsScreen extends Component {
state = {
user: '',
}
componentWillMount() {
this._bootstrapAsync();
}
_bootstrapAsync = async () => {
const user = await AsyncStorage.getItem('user');
this.setState({ user: JSON.parse(user) })
};
render() {
return (
<Container>
<NutrionalToolbar user={this.state.user} />
</Container>
);
}
}
Now inside the NutrionalToolbar component I have this.
import React, { Component } from 'react';
import { View } from 'native-base';
class NutrionalToolbar extends Component {
constructor(props) {
super(props)
console.log(this.props) // This renders an empty user object
}
render() {
console.log(this.props) // This renders the user object with values
return (
<View>
</View>
);
}
}
export default NutrionalToolbar;
How can I get this.props values inside the constructor. I'm getting the values inside render method. Why isn't working inside the constructor?
I would recommend looking into the componentDidUpdate lifecycle hook because, even if you could access the initial user prop in the constructor, you wouldn't be able to access updates to that prop in the constructor.
import React, { Component } from 'react';
import { View } from 'native-base';
class NutrionalToolbar extends Component {
componentDidUpdate() {
console.log(this.props) // This will always log the current props
}
render() {
return (<View></View>);
}
}
export default NutrionalToolbar;

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

Access to component methods in React

I'm using a component called react-input-autosize. The issue I'm facing is that it won't resize the input on viewport resize, so I wan't to manually hook into the component methods and run copyInputStyles() and updateInputWidth().
Pretty new to React so don't know how to achieve this. You can expose the input via the inputRef, but that doesn't really help me no?
My current reduced test case looks like this, would be happy with any pointers on how to run the component methods.
import React from 'react';
import styled from '#emotion/styled';
import AutosizeInput from 'react-input-autosize';
import {throttle} from 'lodash';
const StyledAutosizeInput = styled(AutosizeInput)`
max-width: 100vw;
`;
export default class signUp extends React.Component {
constructor (props) {
super(props);
this.inputRef = React.createRef();
}
componentDidMount() {
console.log(this.inputRef); // outputs input node
window.addEventListener('resize', this.resize);
this.resize();
}
componentWillUnmount() {
window.removeEventListener('resize', this.resize);
}
resize = throttle(() => {
console.log('force resize');
}, 100);
render() {
return (
<StyledAutosizeInput
inputRef={node => this.inputRef = node}
/>
);
}
}
The inputRef={node => this.inputRef = node} callback is referring to the html input element and not the AutosizeInput component. Pass the ref via the ref prop to access the component's methods.
...
resize = throttle(() => {
if (this.inputRef.current) {
this.inputRef.current.copyInputStyles()
this.inputRef.current.updateInputWidth()
}
}, 100);
render() {
return (
<StyledAutosizeInput
ref={this.inputRef}
/>
);
}

Resources