Displaying props in a second target box - javascript

I'm very new to react-native. I'm currently experimenting with it to figure out how I can use it in different ways. Presently, I'm trying to call props of a specifically tapped object and send them to an output box.
So when you tap 'Alan' or 'Steve' their name will appear in the red box.
I'd also like for the dark blue backkground to change to dark red once it's tapped?
I have had a good read of the docs, but I reckon I'm not getting it because it's new to me. I know that I don't seem to be able to access the props of Component which is obviously the class Obj extends
Guidance greatly appreciated.
import React, { Component } from 'react';
import { Text, View, TouchableOpacity } from 'react-native';
import style from './style';
class Obj extends Component {
render(){
return(
<TouchableOpacity
onPressIn={() => this.setState({tapped: true, tappedName: this.props.plrName})}
onPressOut={() => this.setState({tapped: false, tappedName: null})}>
<View style={[style.playerobject, style.shadow]}>
<Text style={[style.plrobjText]}>{this.props.plrName}</Text>
</View>
</TouchableOpacity>
)
}
}
export default class App extends Component {
constructor(props){
super(props);
this.state = {
tapped: false,
tappedName: null,
};
}
render() {
return (
<View style={[style.main]}>
<View style={[style.container, this.state.tapped ? {backgroundColor:'darkred'} : {backgroundColor:'darkblue'} ]}>
<Obj plrName='Alan' />
<Obj plrName='Steve' />
</View>
<View style={style.box }><Text>|{this.state.tapped ? this.state.tappedName : 'x'}|</Text></View>
</View>
);
}
}

import React, { Component } from 'react';
import { Text, View, TouchableOpacity } from 'react-native';
import style from './style';
class Obj extends Component {
onPressIn = () => {
this.props.onPressIn(this.props.plrName)
}
onPressOut = () => {
this.props.onPressOut()
}
render() {
return (
<TouchableOpacity
onPressIn={this.onPressIn}
onPressOut={this.onPressOut}>
<View style={[style.playerobject, style.shadow]}>
<Text style={[style.plrobjText]}>{this.props.plrName}</Text>
</View>
</TouchableOpacity>
)
}
}
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
tapped: false,
tappedName: null,
};
}
onPressIn = (tappedName) => {
this.setState({ tapped: true, tappedName })
}
onPressOut = () => {
this.setState({ tapped: false, tappedName: null })
}
render() {
return (
<View style={[style.main]}>
<View style={[style.container, this.state.tapped ? { backgroundColor: 'darkred' } : { backgroundColor: 'darkblue' }]}>
<Obj plrName='Alan' onPressIn={this.onPressIn} onPressOut={this.onPressOut} />
<Obj plrName='Steve' onPressIn={this.onPressIn} onPressOut={this.onPressOut} />
</View>
<View style={style.box}><Text>|{this.state.tapped ? this.state.tappedName : 'x'}|</Text></View>
</View>
);
}
}

Related

React Native Flatlist ListItem called many times after initial render

Flatlist component as below
<FlatList
data={this.state.data}
keyExtractor={item => item.ID.toString()}
renderItem={this.renderItem}
onRefresh={this.onRefresh}
refreshing={this.state.refreshing}
ListFooterComponent={this.renderFooter}
/>
renderItem = ({ item }) => {
return (
<ListElement onPress={() => this.rowData(item)} item={item}/>
);
};
ListItem Component
import React from "react";
import { Image } from "react-native";
import { Left, Right, Body, Text, ListItem } from "native-base";
import { widthPercentageToDP as wp, heightPercentageToDP as hp } from "react-native-responsive-screen";
import Thumbnails from "../components/Thumbnails";
import styles from "../styles/HomeStyles";
import GlobalStyles from "../constants/GlobalStyles";
class ListElement extends React.Component {
componentDidMount(){
console.log(this.props.item.ID)
}
shouldComponentUpdate(){
return false;
}
render() {
return (
<ListItem onPress={this.props.onPress} thumbnail style={styles.listItem}>
<Left>
<Thumbnails imageURI={require("../../assets/images/female2.png")} />
</Left>
<Body style={{ borderBottomColor: "transparent", top: 2 }}>
<Text
style={{
fontFamily: GlobalStyles.primaryFont,
fontSize: hp("1.85%"),
}}
>
{this.props.item.FirstName} {this.props.item.LastName}
</Text>
<Text
note
style={{
fontFamily: GlobalStyles.primaryFont,
color: "#666666",
fontSize: hp("1.6%"),
}}
>
{this.props.item.Title}
</Text>
</Body>
<Right>
<Image
style={styles.rightArrow}
source={require("../../assets/images/arrowRight.png")}
/>
</Right>
</ListItem>
);
}
}
export default ListElement;
I tried to populate api data on the flatlist. Please refer my above code for implementation. Currently I am facing rerendering issues as mentioned below.
My listitem componentDidMount is invoking multiple times on scroll after even intial render of all listitems.
I have tried PureComponent and shouldComponentUpdate. Thanks in advance.
An Update
Please Find the entire code of Flatlist component
import React, { PureComponent } from "react";
import { View, FlatList } from "react-native";
import { ListItem } from "react-native-elements";
import FL from "../screens/FL";
import FL1 from "../screens/Fl1";
class FlatListDemo extends PureComponent {
constructor(props) {
super(props);
this.state = {
loading: false,
data: [],
error: null,
refreshing: false,
};
}
componentDidMount() {
this.makeRemoteRequest();
}
makeRemoteRequest = () => {
const url = `https://jsonplaceholder.typicode.com/posts`;
this.setState({ loading: true });
fetch(url)
.then((res) => res.json())
.then((res) => {
this.setState({
data: res,
error: res.error || null,
loading: false,
refreshing: false,
});
})
.catch((error) => {
this.setState({ error, loading: false });
});
};
renderItem = ({ item }) => {
return <ListElement onPress={() => this.rowData(item)} item={item} />;
};
render() {
if (this.state.loading === true) {
return <View></View>;
} else {
return (
<View>
<FlatList
data={this.state.data}
keyExtractor={(item) => item.ID.toString()}
renderItem={this.renderItem}
onRefresh={this.onRefresh}
refreshing={this.state.refreshing}
ListFooterComponent={this.renderFooter}
/>
</View>
);
}
}
}
export default FlatListDemo;
Try the following:
add to state a boolean value (you can name it "wasFetched").
Then change the componentDidMount like this:
componentDidMount() {
if(this.state.wasFetched === false) {
this.setState({ wasFetched: true }, () => this.makeRemoteRequest())
}
}

React native - Invariant violation-tried to get frame for out of range index

I have tried to search other posts and forums for the solution to this error. However, either no one has solved those issues or the issues are not really doing the same thing as I am doing. I am getting an error saying " Invariant violation-tried to get frame for out of range index". This happens when I try to input the data into the flatlist from the poke api. Please see code below.
import React, { useState } from "react";
import { View, Text , Button, FlatList, ActivityIndicator } from "react-native";
import { GlobalStyles } from "../styles/GlobalStyles";
class Home extends React.Component {
constructor(props) {
super(props);
this.state = {
isLoading: true,
dataSource: []
}
}
componentDidMount() {
fetch("https://pokeapi.co/api/v2/pokemon/")
.then((res)=> res.json())
.then((response)=> {
this.setState({
isLoading: false,
dataSource: response
})
console.log(response)
})
}
render() {
const showIndicator = this.state.isLoading == true ? <ActivityIndicator size="large" color="#0000ff" /> : null;
return(
<View style={GlobalStyles.container}>
<View style={GlobalStyles.activityIndicator}>{showIndicator}</View>
<FlatList data={this.state.dataSource} renderItem={({item})=> {
return(
<View>
<Text>{item.name}</Text>
</View>
)
}}/>
<Button onPress={()=> this.props.navigation.navigate("About")} title="Go to about"/>
</View>
)
}
}
export default Home;
The thing you are doing wrong is you are sending this.state.datasource is your data attribute, you need to send this.state.dataSource.results
import React, { useState } from "react";
import { View, Text , Button, FlatList, ActivityIndicator } from "react-native";
class Home extends React.Component {
constructor(props) {
super(props);
this.state = {
isLoading: true,
dataSource: []
}
}
componentDidMount() {
fetch("https://pokeapi.co/api/v2/pokemon/")
.then((res)=> res.json())
.then((response)=> {
this.setState({
isLoading: false,
dataSource: response
})
console.log(response)
})
}
render() {
const showIndicator = this.state.isLoading == true ? <ActivityIndicator size="large" color="#0000ff" /> : null;
return(
<View style={{marginTop:100}}>
<View>{showIndicator}</View>
<FlatList data={this.state.dataSource.results}
renderItem={({item})=> {
console.log("item is item",item);
return(
<View>
<Text>{item.name}</Text>
</View>
)
}}/>
<Button onPress={()=> this.props.navigation.navigate("About")} title="Go to about"/>
</View>
)
}
}
export default Home;
Hope this helps!

Checkbox will not render on state update in React Native

I am trying to get a specific checkbox to check and uncheck.
This is the parent component:
import React, { Component } from 'react';
import { View, Text, Modal, TouchableHighlight } from 'react-native'
import { loadLeagues } from '../actions'
import { connect } from 'react-redux'
import Check from './CheckBox'
class LeagueSelect extends Component {
constructor(props) {
super(props)
this.state = {
modalVisible: false,
checked: []
}
}
// state = {
// modalVisible: false,
// checked: []
// }
setModalVisible(visible) {
this.setState({modalVisible: visible})
this.props.league.map(
(v, i) => {
return this.state.checked.push(false)
}
)
}
componentDidMount() {
this.props.loadLeagues()
}
changeCheck = (index) => {
newChecked = this.state.checked.splice(index, 1, !this.state.checked[index])
console.log('newChecked', this.state.checked)
this.setState({ checked: newChecked })
console.log('league checked state', this.state.checked)
}
render() {
return (
<View style={{marginTop: 22}}>
<Modal
animationType="slide"
transparent={false}
visible={this.state.modalVisible}
onRequestClose={() => {
Alert.alert('Modal has been closed.');
}}
>
<View style={{marginTop: 100}}>
<TouchableHighlight
onPress={() => {
this.setModalVisible(!this.state.modalVisible);
}}
>
<Text>Hide Modal</Text>
</TouchableHighlight>
<Text>Leagues</Text>
{this.props.league === null ?'' : this.props.league.map(
(v, i) => {
return(
<View>
<Check
checked={this.state.checked[i]}
index={i}
changeCheck={this.changeCheck}
/>
<Text>{v.acronym}</Text>
</View>
)
}
)}
</View>
</Modal>
<TouchableHighlight
onPress={() => {
this.setModalVisible(true);
}}>
<Text>Show Modal</Text>
</TouchableHighlight>
</View>
);
}
}
function mapStateToProps(state) {
return {
league: state.league.league
}
}
export default connect(mapStateToProps, { loadLeagues })(LeagueSelect)
This is the child component that I'm passing the index of the the checkbox into to update; I'm also passing in the function that updates the state of the checkbox at the specific index:
import React, { Component } from 'react';
import { Text, View } from 'react-native';
import { CheckBox } from 'native-base'
export default class Check extends Component {
constructor(props) {
super(props)
this.state = {
cards: []
}
}
localChange = () => {
this.props.changeCheck(this.props.index)
}
render() {
return(
<CheckBox
checked={this.props.checked}
onPress={this.localChange}
/>
)
}
}
I can see that the state updates when press the checkbox through the console logs that I have setup, but the checkbox isn't updating based off of the new state.

onSubmitEditing never fires?

Really simple question, why isn't onSubmitEditing firing when I hit 'Search' on the virtual keyboard?
Currently there are no errors thrown and the console.log in onSearch() never fires.
I'm using the EXPO SDK v.29.
import React from 'react';
import { StyleSheet, Text, View, TextInput, ScrollView, Image } from 'react-native';
import { WebBrowser } from 'expo';
import Icon from 'react-native-vector-icons/Ionicons';
import Styles from 'app/constants/Styles';
import Vars from 'app/constants/Vars';
import Menu from 'app/components/Menu';
import MiniMap from 'app/components/MiniMap';
import NewsList from 'app/components/NewsList';
import {get, post} from 'app/helpers/api';
export default class HomeScreen extends React.Component {
static navigationOptions = ({ navigation }) => {
return {
headerTitle: (<Image style={{width: 132, height: 30}} source={require('./../../assets/images/header_image.png')}/>)
};
};
constructor(props) {
super(props);
this.state = {
menu: [],
loadingMenu: true,
searchString: '',
};
}
onMenuPress = (item) => {
let next;
let route = item.page_type.slice(4);
if(route == "PageExternal") {
WebBrowser.openBrowserAsync(item.page.url);
} else {
data = item.page;
if(item.children.length > 0) {
route = 'Menu';
data = item.children;
}
this.props.navigation.navigate(route, {
data: data,
title: item.title
});
}
}
onSearch = (e) => {
console.log('onSearch', e);
//WebBrowser.openBrowserAsync('https://www.1177.se/Halland/Sok/?q=Diabetes&submitted=true');
}
async componentDidMount() {
console.log('Eat my shorrs');
menuitems = await get('content/menu');
this.setState({
menu: menuitems,
loadingMenu: false,
})
//this._getMenu();
}
render() {
return (
<ScrollView style={Styles.whiteBackground}>
<View style={[Styles.blueBackground, Styles.topPadding, Styles.horizontalPadding]}>
<View style={[Styles.searchBox, Styles.bottomMargin]}>
<View style={Styles.searchField}>
<TextInput
style = {Styles.searchInput}
placeholder = "Sök sjukdom/behandling"
onSubmitEditing = {(e) => (this.onSearch(e))}
underlineColorAndroid = "transparent"
returnKeyLabel = "Sök på 1177"
returnKeyType = "search"
/>
<Icon style = {Styles.searchIcon} name = "ios-search" size={18}/>
</View>
<Text style={[Styles.searchLabel]}>Söksvaren kommer från 1177.se</Text>
</View>
<Menu
data={this.state.menu}
loading={this.state.loadingMenu}
style={Styles.topPadding}
onItemPress={this.onMenuPress}
/>
</View>
<Text style={[Styles.h1, Styles.blackText, Styles.horizontalPadding]}>Hitta till oss</Text>
<MiniMap navigation={this.props.navigation}></MiniMap>
<Text style={[Styles.h1, Styles.blackText, Styles.horizontalPadding]}>Nyheter</Text>
<NewsList navigation={this.props.navigation}></NewsList>
</ScrollView>
);
}
}
<TextInput
onSubmitEditing = {(event) => (this.onSearch(event.nativeEvent.text))}
multiline={false}
/>
It does not work when multiline={true} is specified, perhaps your styles has that. See Documentation
You will find your text with event.nativeEvent.text
Try changing
onSubmitEditing = {(e) => (this.onSearch(e))}
to
onSubmitEditing = {this.onSearch}
Then keep
onSubmitEditing = {(e) => this.onSearch(e)}
like this and try by changing the function like below
function onSearch(e) {
console.log('onSearch', e);
//WebBrowser.openBrowserAsync('https://www.1177.se/Halland/Sok/?q=Diabetes&submitted=true');
}
Hope this will work
Check this out
https://snack.expo.io/#raajnadar/submit-text-input
Render method
render() {
return (
<View style={styles.container}>
<TextInput
placeholder="Sök sjukdom/behandling"
onSubmitEditing={this.onSearch}
underlineColorAndroid="transparent"
returnKeyLabel="Sök på 1177"
returnKeyType="search"
style={{ width: '100%', textAlign: 'center' }}
/>
</View>
);
}
On submit function
onSearch() {
console.log('onSearch')
}

React Native : 'undefined is not a function' while using navigator

I am trying to make an app with 2 panels, one with my user inputs, and the other one with the output (it's all dates, not important).
I am using navigator. My 'main' class is :
export default class App extends Component {
onDateChange = (state) => (event,value) => {
this.setState({
[state]:value
});
}
render () {
return (
<Navigator
initialRoute={{id: 'mainPage', name: 'main'}}
renderScene={this.renderScene.bind(this)}
configureScene={(route) => {
if (route.sceneConfig) {
return route.sceneConfig
}
return Navigator.SceneConfigs.VerticalDownSwipeJump;
}}/>
);
}
renderScene ( route, navigator ) {
var routeId = route.id;
if (routeId === 'mainPage') {
return (
<mainPage
navigator={navigator}/>
);
}
if (routeId === 'calcPage') {
return (
<calcPage
navigator={navigator}/>
);
}
}
}
And the first page it loads looks like :
class mainPage extends Component {
componentWillMount () {
var navigator = this.props.navigator;
}
constructor(props) {
super(props)
this.state = {
dayMes: "",
monthMes: "",
yearMes: "",
dayLast: "",
monthLast: "",
yearLast: "",
dayInit: "",
monthInit: "",
yearInit: "",
}
}
render() {
return (
<ScrollView>
<View style={{
justifyContent: 'center',
}}>
<View style={{
height: 40,
justifyContent: 'center',
borderTopWidth: 25,
backgroundColor: 'white'
}}/>
</View>
LOTS of textInputs ...
<TouchableOpacity onPress={ () => { navigator.replace({ id: 'calcPage' }); } }>
<View style={styles.button}>
<Text style={styles.buttonText}>Calculer</Text>
</View>
</TouchableOpacity>
</View>
</ScrollView>
)
}
}
When i press the button though, it gives me an error undefined is not a function (evaluating 'navigator.replace({id: 'calcPage'})'). I guess the problem is with the function it triggers, but i don't know where. The calcPage class is the same as the first one, since i'm still testing.
Thanks for the help !
EDIT :
import React, {Component} from 'react';
import DatePicker from 'react-native-datepicker';
import { AppRegistry, View, Image, Text, TextInput, StyleSheet, Alert, Button, TouchableOpacity, ScrollView, Navigator } from 'react-native';
my imports

Categories

Resources