how to get state from child component - react-native

I need to get the state of the number from the component Numberplus
And display in the App component
app component:
import React from "react";
import { Text, View } from "react-native";
import Numberplus from "./Number";
function App() {
return (
<View>
<Text>{/* How to get Numberplus component State here */ Number}</Text>
<Numberplus />
</View>
);
}
export default App;
Numberplus component:
import { Button, Text, View } from "react-native";
function Numberplus() {
let [Number, setNamber] = useState(0);
return (
<View>
{/*<Text>{Number}</Text>*/}
<Button
onPress={() => {
setNamber(++Number);
}}
title="Plus"
/>
</View>
);
}
export default Numberplus;
See more details and display the output result

You can solve this problem either using redux or holding the state in your parent component. I can not explain whole redux here but here is how you can manage it with state.
App.js
import React from "react";
import { Text, View } from "react-native";
import Numberplus from "./Number";
function App() {
let [Number, setNumber] = useState(0);
return (
<View>
<Text>{/* How to get Numberplus component State here */ Number}</Text>
<Numberplus number={Number} onPress={() => {
setNumber(++Number);
}} />
</View>
);
}
export default App;
NumberPlus.js
import { Button, Text, View } from "react-native";
function Numberplus() {
return (
<View>
{/*<Text>{this.props.number}</Text>*/}
<Button
onPress={this.props.onPress}
title="Plus"
/>
</View>
);
}
export default Numberplus;

Related

How to pass state to component ? React Native

I want to pass a state with value - 3 to another functional component that uses value - 1. How can I do that ?
My code:
Screen 1.
import { Text, TouchableOpacity } from "react-native";
import React from "react";
import { useNavigation } from "#react-navigation/native";
export default function ScreenOne() {
const navigation = useNavigation();
const [myState, setMyState] = useState(1);
return (
<TouchableOpacity
onPress={() =>
navigation.navigate("ScreenTwo", setMyState(myState(3)))
}
>
<Text>Go to another screen</Text>
</TouchableOpacity>
); }
Screen 2.
import { View, Text } from "react-native";
import React from "react";
import { useRoute } from "#react-navigation/native";
export default function screenTwo() {
const [myState, setMyState] = useState(1);
const route = useRoute();
const setMyState = route.params;
return (
<View>
<Text>myState</Text>
</View>
); }
For example, the myState in the first screen has the value 1, after clicking the button in the first screen I need to change the value of myState the state 3 in the second screen.
To share state between two sibling function components you need to lift the state up to their common parent component. The state must be located only in the parent.
First screen: you just need to handle the new state and lift up to the parent component.
export default function ScreenOne({ handleState }) {
const navigation = useNavigation();
return (
<TouchableOpacity
onPress={() => {
handleState(3)
navigation.navigate("ScreenTwo")
}}
>
<Text>Go to another screen</Text>
</TouchableOpacity>
);
}
Second screen: you only need to get state value.
export default function ScreenTwo({ stateĀ }) {
return (
<View>
<Text>{state}</Text>
</View>
);
}
Parent component: you have your useState here, so childs components can interact with it like this.
function Parent() {
const [state, setState] = useState(1);
return {
<View>
<ScreenOne handleState={(state) => setState(state)} />
<ScreenTwo state={state} />
</View>
}
}

React-Native TextInput one step behind in Child Component

TextInput in Child Component on logging is one step behind in my Input
Parent Component:
import React from 'react';
import {
View,
Text,
} from 'react-native';
import NumberInput from '../../Components/NumberInput'; //child component
class Login extends React.Component {
constructor(props) {
super(props);
this.state = {
number: '',
};
}
onChange = value => {
this.setState({number: value});
console.log(this.state.number);
};
render() {
return (
<View>
<Text>Login</Text>
<NumberInput onChange={this.onChange} />
</View>
);
}
}
Child Component
import React from 'react';
import {View, Text, TextInput} from 'react-native';
import {withNavigation} from 'react-navigation';
const NumberInput = ({onChange}) => {
return (
<View>
<Text>Enter mobile number to continue</Text>
<TextInput
style={styles.input}
keyboardType={'phone-pad'}
placeholder="999-999-9999"
underlineColorAndroid="transparent"
autoCompleteType="tel"
maxLength={10}
onChangeText={value => onChange(value)}
/>
</View>
);
};
export default withNavigation(NumberInput);
Pass your console.warn() as a callback to this.setState()
this.setState({
number: value
},() => {
console.warn(this.state.number);
});

Identifier has already been declared react native

So I have created a simple react-native following the Coursera lectures.
My Menu component just holds a list of recipes and displays them on the device.
import React, { Component } from 'react';
import { View, FlatList } from 'react-native';
import { ListItem } from 'react-native-elements';
function Menu(props){
const renderMenuItem = ({item, index}) => {
return(
<ListItem
key={index}
title={item.name}
subtitle={item.description}
hideChevron={true}
onPress={() => props.onPress(item.id)}
leftAvatar={{ source: require('./images/uthappizza.png')}}
/>
);
}
return(
<FlatList
data={props.dishes}
renderItem={renderMenuItem}
keyExtractor={item => item.id.toString()}
/>
)
}
export default Menu;
Next, there is the DishdetailComponent which renders the details of each dish.
import React from 'react';
import { Text, View } from 'react-native';
import { Card } from 'react-native-elements';
function RenderDish(props) {
const dish = props.dish;
if (dish != null) {
return(
<Card
featuredTitle={dish.name}
image={require('./images/uthappizza.png')}>
<Text style={{margin: 10}}>
{dish.description}
</Text>
</Card>
);
}
else {
return(<View></View>);
}
}
function Dishdetail(props) {
return(<RenderDish dish={props.dish} />);
}
export default Dishdetail;
And finally, I have the MainComponent which is like the top component holding the two previous components.
import { View } from 'react-native';
import { DISHES } from '../shared/dishes';
import Dishdetail from './DishdetailComponent';
class Main extends Component {
constructor(props){
super(props);
this.state = {
dishes: DISHES,
selectedDish: null
};
}
onDishSelect(dishId) {
this.setState({selectedDish: dishId})
}
render(){
return(
<View style={{flex:1}}>
<Menu dishes={this.state.dishes} onPress={(dishId) => this.onDishSelect(dishId)} />
<Dishdetail dish={this.state.dishes.filter((dish) => dish.id === this.state.selectedDish)[0]} />
</View>
);
}
}
export default Main;
When I run the app I get this
Did I miss something? Here is my repo if you want to have a closer look.
Few moments here:
1) Seems you forgot to import the Menu component at the top of imports
2) You simply have a typo in the import of DishdetailComponent
Just paste these lines instead of yours
import { View } from "react-native";
import { DISHES } from "../shared/dishes";
import Dishdetail from "./DishDetailComponent";
import Menu from "./MenuComponent";
Also, sometimes bunder crashes and don't reload.
To fix this I would suggest using
yarn start --reset-cache command (but don't forget to kill previous Metro Bundler instance) :)

Render list item using FlatList in React Native and Firebase

Very new to react-native. I am not sure how data is passed into the Flatlist and how to render it. I am passing in the Restaurants array from firebase database to this.restaurantRef. listenForRestaurants is called when first rendered to push all the referenced items into an array called restaurants. Not quite sure how I should put the logic for rendering the list of restaurants from firebase database.
import React from 'react'
import {Component} from 'react'
import {
ScrollView,
Text,
FlatList,
} from 'react-native'
import firebase from '../firebase'
import ListItem from './ListItem'
export default class Location extends Component {
constructor(props){
super(props)
this.restaurantRef = firebase.database().ref().
child('Restaurants')
}
listenForRestaurants(restaurantRef) {
restaurantRef.on('value', (snapshot) => {
var restaurants = [];
snapshot.forEach((child) => {
restaurants.push({
name: child.val().name,
_key: child.val().key
})
})
})
}
componentDidMount(){
this.listenForRestaurants(this.restaurantRef)
}
_renderItem(item){
return(
<ListItem item={item} onPress={() => {}} />
)
}
render(){
return(
<ScrollView>
<FlatList
data={this.restaurantRef}
renderItem={this._renderItem}
/>
</ScrollView>
)
}
}
//This the ListItem component
import React, {Component} from 'react'
import {
View,
TouchableHighlight,
Text,
} from 'react-native';
export default class ListItem extends Component {
render() {
return (
<TouchableHighlight onPress={this.props.onPress}>
<View>
<Text>{this.props.item.name}</Text>
</View>
</TouchableHighlight>
);
}
}

react-native redux dispatch action from nested components

I am wondering how I can dispatch an action from n-th level nested components. This is wha I have got:
BodyContainer (contains connect, mapProps, mapDispatch, etc.) => Body
=Body (Component) where the actions are dispatched)
==Grid (Component)- state is passed as props from Body and some elements parts of the state are further passed on to the next component as props.
===Square (Component) - receives some part of the state as props.
Now, I'd like to dispatch an action from the Square component to change the state. I thought I'll just do a SquareContainer first but then how would it get the parts of the state from Grid?
See below the components (let me know if you need more information):
BodyContainer:
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import { listNumbers, pickNumber } from '../actions/numberActions';
import { populateRow, populateGrid } from '../actions/gridActions';
import Body from '../components/Body';
const mapStateToProps = state => ({
numbers: state.numbers,
grid: state.grid
});
const mapDispatchToProps = dispatch => (
bindActionCreators({
listNumbers,
pickNumber,
populateRow,
populateGrid
}, dispatch)
);
export default connect(
mapStateToProps,
mapDispatchToProps
)(Body);
Body Component
import React, { Component, PropTypes } from 'react';
import { View, StyleSheet, Button } from 'react-native';
import Grid from './Grid';
import * as globalStyles from '../styles/global';
export default class Body extends Component {
componentWillMount() {
this.refresh();
}
refresh() {
this.props.populateGrid();
}
render() {
return (
<View style={styles.body}>
<Grid inGrid={this.props.grid} />
<View style={styles.buttonContainer}>
<Button
onPress={this.refresh.bind(this)}
title={'Regenerate the Grid'}
/>
</View>
</View>
);
}
}
Grid component
import React, { Component, PropTypes } from 'react';
import { View, StyleSheet } from 'react-native';
import Square from './Square';
import * as globalStyles from '../styles/global';
export default class Grid extends Component {
render() {
const row = [];
let i = 0;
this.props.inGrid.forEach((r) => {
r.forEach((c) => {
i++;
row.push(
<Square key={i} sqValue={c} />
);
});
});
const { grid } = styles;
return (
<View style={grid}>
{row}
</View>
);
}
}
Square Component
import React, { PropTypes } from 'react';
import { View, Text, StyleSheet, TouchableHighlight } from 'react-native';
import * as globalStyles from '../styles/global';
const Square = ({ sqValue }) => {
const { square, textStyle, squareActive } = styles;
return (
<TouchableHighlight
style={[square, sqValue[1] && squareActive]}
onPress={() => console.log(sqValue[0])}
>
<View>
<Text style={textStyle}>{sqValue[0]},{sqValue[1]}</Text>
</View>
</TouchableHighlight>
);
};
Edit: I've changed the Square component to a stateful one:
import React, { Component, PropTypes } from 'react';
import { View, Text, StyleSheet, TouchableHighlight } from 'react-native';
import * as globalStyles from '../styles/global';
export default class Square extends Component {
render() {
const { square, textStyle, squareActive } = styles;
const { sqValue } = this.props;
return (
<TouchableHighlight
style={[square, sqValue[1] && squareActive]}
onPress={() => console.log(sqValue[0])}
>
<View>
<Text style={textStyle}>{sqValue[0]},{sqValue[1]}</Text>
</View>
</TouchableHighlight>
);
}
}
I'd like to dispatch an action from onPress={}. Thank you