FlatList renderItem is firing, console.logs are visible, but text is not. What happened to the text? - react-native

I have a harcoded a JSON object just to make sure that the items inside the FlatList will be rendered properly. I can read all of the console.logs I wrote inside, but none of the Text is appearing. Any ideas why?
here is the code:
import {
View,
FlatList,
Text,
TouchableWithoutFeedback,
AsyncStorage,
ScrollView,
Picker
} from 'react-native'
import { NavigationActions } from 'react-navigation';
import { Header, Card, CardSection, Button, Input } from '../common';
import Config from '../Config';
export default class CustomStore extends Component {
constructor(props) {
super(props);
this.state = {
stores: [],
forceRedraw: false
};
}
static defaultProps = {
//stores:[{"place": "youngja", "id": "1"},{"place": "tasty", "id": "2"}]
};
componentWillMount() {
const newJSON = {"gym":{"id":"1", "day": "Sunday"}, "restaurant":{"id": "2", "day": "Monday"}};
const JSArr = Object.values(newJSON);
//console.log(JSArr);
this.setState({
stores: JSArr
});
}
deleteEntry() {
console.log('this is working')
}
renderListOfStores() {
return <FlatList
data={this.state.stores}
renderItem={ (item) => {
console.log('here is your thing',item);
this.singleStore(item)}
}
keyExtractor={(item) => item.id}
/>;
}
singleStore(item) {
return <View>
{console.log('inside the singleStore method')}
<Card>
<Text>hello{console.log('this is inside the text tag')}{item.day}</Text>
<Button
onPress={() => this.deleteEntry()}
>
<Text>Press this to delete this entry</Text>
</Button>
</Card>
</View>;
}
render() {
return(
<ScrollView>
<Header headerText="Custom Store Screen"/>
<Text>This should be a list of stores</Text>
{this.renderListOfStores()}
<Text>This is the end of the list</Text>
</ScrollView>
)
}
}
As you can see, I've put console.logs inside the renderListOfStores method to verify that it's being fired. I have another console.log inside the singleStore method..this console log is also visible..as is the last console log inside the tag. No idea why I'm able to read console.logs, but none of the text

you need to put return before this.singleStore() inside your renderItem props.

Related

React call function and setstate when go back to a previous screen

I'm new in React's world
I have 2 screens : Stock and Barcode.
In Stock, i navigate to Barcode's screen.
When i scan a barcode, i go back to the previous screen I would like to set the input text with the barcode and call a function. In my example joinData();
The problem is to set the input text and call a function.
I tried examples and answers but i don't find or don't understand how to to that.
I tried something in componentDidUpdate() but it fails
Invariant Violation:Maximum update depth exceeded
Stock.js
import React, {useState} from "react";
import { ScrollView, TouchableWithoutFeedback, Dimensions, StyleSheet, FlatList, View, Alert, TouchableOpacity, TextInput } from 'react-native';
//galio
import { Block, Text, theme } from "galio-framework";
import { Button, Icon, Input } from "../components/";
export default class Stock extends React.Component {
constructor(props) {
super(props);
this.myRef = React.createRef();
this.array = [];
this.state = {
arrayHolder: [],
Input_ITMREF: ''
};
}
// I tried this but it fails
componentDidUpdate() {
if (this.props.navigation.getParam('itmref') != 'undefined') {
this.setState({ Input_ITMREF: this.props.navigation.getParam('itmref')});
}
}
componentDidMount() {
this.setState({ arrayHolder: [...this.array] }) // Rafraîchit la liste
}
joinData = () => {
vxml = this.state.Input_ITMREF+" I do something";
}
Render() {
return (
<Block flex>
<Block row space="evenly">
<Block center>
<Input
placeholder='Code article'
onChangeText={data => this.setState({ Input_ITMREF: data })}
ref={this.myRef}
/>
</Block>
</Block>
<Block center>
<Button style={styles.button} onPress={() => this.props.navigation.navigate('Barcode')}>Barcode</Button>
<Text style={{ margin: 10 }}>Post: {this.props.navigation.getParam('itmref')}</Text>
</Block>
</Block>
);
}
}
And Barcode.js
import React, {} from 'react';
import { ScrollView, TouchableWithoutFeedback, Dimensions, StyleSheet, FlatList, View, Alert, TouchableOpacity, TextInput } from 'react-native';
import { BarCodeScanner } from 'expo-barcode-scanner';
import { Button } from "../components/";
export default class Barcode extends React.Component {
static navigationOptions = {
header: null //hide the header bar
};
handleBarCodeScanned = ({ type, data }) => {
this.props.navigation.navigate("Stock", {
itmref: data
});
};
render() {
return (
<BarCodeScanner
onBarCodeScanned={this.handleBarCodeScanned}
style={styles.barcodeScanner}
/>
);
}
}
You can pass a state handler function as prop to Barcode screen and use that to set value for textInput in state.
in Stock(in state)
state = {
inputValue: ''
}
....
const setInputTextValue= (newValue) => {
this.setState({
inputValue: newValue
})
you pass this function as prop to Barcode scene and call it whenever you wanna set a new value(considering Stock scene is still mounted).
UPDATE: What is the proper way to update a previous StackNavigator screen?
also another solution i just saw: Updating State of Another Screen in React Navigation
You need to use WillFocus method(Included in react-navigation) when you comeback from Barcodepage to stockPage
componentDidMount(){
console.log("willFocus runs") initial start
const {navigation} = this.props;
navigation.addListener ('willFocus', async () =>{
console.log("willFocus runs") // calling it here to make sure it is logged at every time screen is focused after initial start
});
}
For More Information read this document
https://reactnavigation.org/docs/function-after-focusing-screen/

React Native State is Undefined Vasern

I am actually starting with Mobile Development and React Native and I thought an interesting Database called Vasern But now I am trying to load things from my database with the componentDidMount() method but i actually just get this Error everytime.
I am sure its just a trivial Error but i just cant find it...
Thanks in Advance
import React, {Component} from 'react';
import {
StyleSheet,
Text,
View,
TextInput,
Button,
SectionList
} from 'react-native';
import Vasern from 'vasern';
import styles from './styles';
const TestSchema = {
name: "Tests",
props: {
name: "string"
}
}
const VasernDB = new Vasern({
schemas: [TestSchema],
version: 1
})
const { Tests } = VasernDB;
var testList = Tests.data();
class Main extends Component {
state = {
tests: [],
};
constructor(props){
super(props);
this._onPressButton = this._onPressButton.bind(this);
this._onPressPush = this._onPressPush.bind(this);
this._onPressUpdate = this._onPressUpdate.bind(this);
this._onPressDeleteAll = this._onPressDeleteAll.bind(this);
}
componentDidMount() {
Tests.onLoaded(() => this._onPressButton());
Tests.onChange(() => this._onPressButton());
}
_onPressButton = () => {
let tests = Tests.data();
console.log(tests);
//if( tests !== undefined){
this.setState({tests}); // here is the error
//alert(tests);
//}
}
_onPressPush = () => {
Tests.insert({
name: "test"
});
console.log(this.state.tests + "state tests"); //here the console only shows the text
}
_onPressUpdate = () => {
var item1 = Tests.get();
Tests.update(item1.id, {name: "test2"});
}
_onPressDelete = () => {
}
_onPressDeleteAll = () => {
let tests = Tests.data();
tests.forEach((item, i) => {
Tests.remove(item.id)
});
}
_renderHeaderItem({ section }) {
return this._renderItem({ item: section});
}
_renderItem({ item }){
return <View><Text>{item.name}</Text></View>
}
render() {
//const { tests = [] } = this.props;
return (
<View style={styles.container}>
<View>
<TextInput> Placeholder </TextInput>
<Button title="Press me for Show" onPress={this._onPressButton}/>
<Button title="Press me for Push" onPress={this._onPressPush}/>
<Button title="Press me for Update" onPress={this._onPressUpdate}/>
<Button title="Press me for Delete" onPress={this._onPressDelete}/>
<Button title="Press me for Delete All" onPress={this._onPressDeleteAll}/>
</View>
<View style={styles.Input}>
<SectionList
style={styles.list}
sections={this.state.tests}
keyExtractor={item => item.id}
renderSectionHeader={this._renderHeaderItem}
contentInset={{ bottom: 30 }}
ListEmptyComponent={<Text style={styles.note}>List Empty</Text>}
/>
</View>
</View>
);
}
}
export default Main;
Since Tests.data() will return an array (as list of records).
In React Native, you might use FlatList to display an array of records.
import { ..., FlatList } from 'react-native';
...
// replace with SectionList
<FlatList
renderItem={this._renderItem} // item view
data={this.state.tests} // data array
style={styles.list}
keyExtractor={item => item.id}
contentInset={{ bottom: 30 }}
ListEmptyComponent={<Text style={styles.note}>List Empty</Text>}
/>
In case you want to use SectionList, you will need to reform data into sections. Something like:
var sections = [
{title: 'Title1', data: ['item1', 'item2']},
{title: 'Title2', data: ['item3', 'item4']},
{title: 'Title3', data: ['item5', 'item6']},
]
Besides, React Native is in a really good state. I think you will like it.

React Native Modal crashes app on load

I'm trying to create a small request box that pops up from the bottom of the screen to let a user confirm a reservation. A mockup of what that could look like is below. After some research, a modal seemed like the way to go.
The Problem
Starting the app with a <Modal /> freezes the app on the home screen. Loading the modal when needed (in the code below) crashes the app with no error.
Code
Component rendering the <Model /> (called as <RequestTeacherPopup />)
// #flow
import React from 'react'
import { ScrollView, View } from 'react-native'
...
export default class RequestScreen extends React.Component<Props, {nextSeminar: DateTime, teachers: []}> {
constructor (props: Props) {
super(props)
...
this.state = {
nextSeminar: nextSeminar,
teachers: null,
requestVisibility: false,
requestedTeacher: null
}
}
...
render () {
var teacherList = []
if (this.state.teachers) {
for (let teacherItem of this.state.teachers) {
if (teacherItem.key !== this.props.profile.defaultSeminar) {
let teacher: Teacher = teacherItem.value
let teacherPic: {uri: string} = ('picture' in teacher) ? { uri: teacher.picture } : null
teacherList.push(
<ListItem
roundAvatar
avatar={teacherPic}
onPressRightIcon={
function () {
this.setState({
requestVisibility: true,
requestedTeacher: teacher
})
}.bind(this)
}
key={teacherItem.key}
title={`${teacher.firstName} ${teacher.lastName}`}
subtitle={`${teacher.taughtCourses} | Room ${teacher.room}`} />
)
}
}
}
return (
<View style={styles.mainContainer}>
<ScrollView>
<List>
{teacherList}
</List>
{
(this.state.requestVisibility)
? (<RequestTeacherPopup
requestedTeacher={this.state.requestedTeacher}
onFinish={() => this.setState({ requestVisibility: false })} />)
: null
}
</ScrollView>
</View>
)
}
}
RequestTeacherPopup Component
// #flow
import React, { Component } from 'react'
import { View, Image, Text } from 'react-native'
import { Divider, Overlay } from 'react-native-elements'
import Modal from 'react-native-modal'
...
class RequestTeacherPopup extends Component<{isVisible: boolean, requestedTeacher: Teacher, onFinish: () => void}> {
state = {
markedDates: this.getDaysInMonth(DateTime.local().month, DateTime.local().year, DISABLED_DAYS),
calVisiblity: false,
requestedDate: null,
requestedDay: null
}
...
render () {
return (
<Modal
style={Styles.bottomModal}
isVisible
onSwipe={this.handleRequest}
swipeDirection='up' >
...
</Modal>
)
}
}
The problem still occurs when the <Modal /> is not passed any children, and I have tried both the built in modal and the react-native-modal package from npm.
Thanks for any help!
Hello while showing or closing any modal,
you have use setTimeout(()=>{},miliseconds)
modal is an external window of the screen that covers the whole screen.

React Native - OnPress button not working

I have a button with a onPress event i am trying to simply console log that the button was successfully pressed.
The button is within my template file i have extracted this portion of code to a separate file, ive done the same for my tyles.
The add() function associated with the press does not fire when i press the add button, so the console.log does not show.
But the console.log does does show on initial load of the screen ( i dont know why this is )
items.screen.js
import React, { Component } from 'react';
import { StyleSheet, Text, View, TextInput } from 'react-native';
import style from './items.style'
import template from './items.template';
export default class ItemsScreen extends Component {
static navigationOptions = {
title: "Items"
}
constructor(props) {
super(props);
this.state = { text: '' };
}
add() {
console.log("pressed add button");
}
render() {
return template(this, style);
}
}
items.template.js
import React, { Component } from 'react';
import { Text, View, TextInput, Button } from 'react-native';
import { style } from './items.style'
export default (template, style) => {
return (
<View style={style.container}>
<TextInput
style={{ width: 300 }}
value={template.state.text}
onChangeText={(text) => template.setState({ text })}
/>
<Button
onPress={template.add()}
title="Add"
/>
</View>
);
}
You are not assigning template.add to the on press event, instead your code is executing the add function and attempting to assign the result of that to the onPress event.
I find the following two options to be cleaner than the other suggestions:
Create a local onPress Handler (in items.template)
onPress = () => {
template.add();
}
and then
onPress={this.onPress} //note the lack of parentheses `()`
or
create an inline function
onPress={() => template.add()}
You should pass function in attribute,not function call, so it should be
<Button
onPress={template.add.bind(template)}
title="Add"
/>

react native pass props to another component

I've been struggling passing a value from one component to another. It's a continuation of the issue from a previous question which was partially resolved: react-native tab navigator search box
I'm using tab navigator and here's my app setup:
index.js (renders tab setup)
  router.js
     searchHeader.js
     tab1.js
     tab2.js
     etc
In index.js when a tab is changed I'm getting the name of the tab. I want to pass that to searchHeader.js to update the placeholder text.
As searchHeader.js isn't imported into index.js and not a direct child how do I pass it that value?
index.js
import React, { Component } from 'react';
import { Root, Tabs } from './config/router';
import { Alert,View } from 'react-native';
class App extends Component {
constructor(props) {
super(props);
this.state = {
searchText: '',
}
}
_getCurrentRouteName(navState) {
if (navState.hasOwnProperty('index')) {
this._getCurrentRouteName(navState.routes[navState.index])
} else {
if (navState.routeName==='One') {
this.setState({searchText:'Search One'})
}
if (navState.routeName==='Two') {
this.setState({searchText:'Search Two'})
}
if (navState.routeName==='Three') {
this.setState({searchText:'Search Three'})
}
if (navState.routeName==='Four') {
this.setState({searchText:'Search Four'})
}
}
}
render() {
return (
<Root onNavigationStateChange={(prevState, newState) => {
this._getCurrentRouteName(newState)
}} />
)
}
}
export default App;
router.js
...
export const Root = StackNavigator({
Tabs: {
screen: Tabs,
navigationOptions: {
header: <SearchHeader data={'Test'} />
}
},
}, {
mode: 'modal',
});
searchHeader.js
import React, { Component } from 'react';
import { View,Text,Dimensions,Alert } from 'react-native';
import { SearchBar } from 'react-native-elements';
class SearchHeader extends Component {
constructor(props) {
super(props);
this.state = {
placeholder: "Search One"
}
}
render() {
return (
<SearchBar
noIcon
containerStyle={{backgroundColor:'#fff'}}
inputStyle={{backgroundColor:'#e3e3e3',}}
lightTheme = {true}
round = {true}
placeholder={data}
placeholderTextColor = '#000'
/>
);
}
};
export default SearchHeader;
You could perhaps pass it as a navigation prop using the setParams method.
An alternative, depending on the scope of your app, would be to look at a state library such as Redux or MobX - but if it's a small app, it's overkill
For that you can use Redux, you will have a store where you can put shared properties and values,
Then your components can connect to that store and bind its props with the chosen reducer(s) and dispatch actions..
this structure may work:
class Home extends Component {
func(val) {
this.setState({value: val});
}
render() {
return (
<View>
<Two func={(val) => this.func(val)} />
</View>
)
}
}
class Two extends Component {
render() {
return (
<View>
<Button title="set" onPress={() => this.props.func('data')} />
</View>
)
}
}