React Native setState not causing rendering - reactjs

I'm a complete beginner at react native and now I'm stuck with an update problem. I'm using react-native-paper and typescript.
In my app, I want to press a button and then the text field should change its text.
The problem is somehow at the button, or the called function because in the console log its always "before: true after:true" or "before: false after:false",
but what I expected is "before: true after: false" or vice-versa
I've also got a second Text View which is not shown at all.
Maybe someone can tell me what I am doing wrong?
My index.js
import * as React from 'react';
import { AppRegistry } from 'react-native';
import { Provider as PaperProvider } from 'react-native-paper';
import App from './src/App';
export default function Main() {
return (
<PaperProvider>
<App />
</PaperProvider>
);
}
AppRegistry.registerComponent('main', () => Main);
My MyNavigation.tsx (which contains currently my whole app).
import * as React from 'react';
import { BottomNavigation, Text, Avatar, Button, Card, Title, Paragraph, Banner } from 'react-native-paper';
import { View, Image, WebView } from 'react-native';
export default class MyNavi extends React.Component {
constructor(props, context) {
super(props, context);
this.setUnConnected = this.setUnConnected.bind(this);
}
state = {
index: 0,
routes: [
{ key: 'viewcamera', title: 'View', icon: 'remove-red-eye' },
{ key: 'viewsettings', title: 'Settings', icon: 'settings' },
{ key: 'viewhelp', title: 'How-To', icon: 'help' },
],
visible: true,
connected: false,
};
_handleIndexChange = index => { this.setState({ index }); }
setUnConnected = function () {
console.log("before: " + this.state.connected);
this.setState({ connected: !this.state.connected });
console.log("after: " + this.state.connected);
console.log("--------------");
};
ViewRoute = () =>
<View style={{ flex: 1, marginTop: 40 }}>
{/* --------- This text field does not get updated -------------*/}
<Text>connected: {this.state.connected ? 'true' : 'false'}</Text>
{/* --------- This text field is not shown at all ------------*/}
<Text>
{this.state.connected}
</Text>
<Button icon="camera" mode="contained" onPress={this.setUnConnected}>
Press me
</Button>
<View style={{ height: 400, width: 400 }}>
<WebView
source={{ uri: 'https://stackoverflow.com/' }}
style={{ marginTop: 40 }}
// onLoad={() => this.setState({ connected: true })}
/>
</View>
</View>
SettingsRoute = () => <Text>Settings</Text>;
HelpRoute = () => <View></View>
_renderScene = BottomNavigation.SceneMap({
viewcamera: this.ViewRoute,
viewsettings: this.SettingsRoute,
viewhelp: this.HelpRoute,
});
render() {
return (
<BottomNavigation
navigationState={this.state}
onIndexChange={this._handleIndexChange}
renderScene={this._renderScene}
/>
);
}
}

State Updates May Be Asynchronous React Documentation
So You cannot test your console.log in this way. Use the callback function of setState method as follows,
this.setState({ connected: !this.state.connected }, () => {
console.log("after: " + this.state.connected);
console.log("--------------");
});
Hope this will help you.

Your issue is here,
setUnConnected = function () {
console.log("before: " + this.state.connected);
this.setState({ connected: !this.state.connected });
console.log("after: " + this.state.connected);
console.log("--------------");
};
setState is async function and it takes some time to update the state. It does not block execution of next statements. So you will always get the previous state only for both the console.log.
To get the actual updated value, you should use callback in setState.
setUnConnected = function () {
console.log("before: " + this.state.connected);
this.setState({ connected: !this.state.connected }, () => console.log("after: " + this.state.connected); ); //Now you will get updated value.
console.log("--------------");
};
For this,
{/* --------- This text field is not shown at all ------------*/}
<Text>
{this.state.connected}
</Text>
this.state.connected is either true or false (Boolean) which will never be shown on screen. If you still want to see the value on screen, then you can use this hack.
<Text>
{this.state.connected.toString()}
</Text>
Update
From the docs,
Pages are lazily rendered, which means that a page will be rendered the first time you navigate to it. After initial render, all the pages stay rendered to preserve their state.
Instead of this,
_renderScene = BottomNavigation.SceneMap({
viewcamera: this.ViewRoute,
viewsettings: this.SettingsRoute,
viewhelp: this.HelpRoute,
});
You should use this version of renderScene,
_renderScene = ({ route, jumpTo }) => {
switch (route.key) {
case 'viewcamera':
return <ViewRoute jumpTo={jumpTo} connected={this.state.connected} setUnConnected={this.setUnConnected}/>; //Here you can pass data from state and function to your component
case 'viewsettings':
return <SettingsRoute jumpTo={jumpTo} />;
case 'viewhelp':
return <HelpRoute jumpTo={jumpTo} />;
}
}
Your complete code should look like this,
import * as React from 'react';
import { BottomNavigation, Text, Avatar, Button, Card, Title, Paragraph, Banner } from 'react-native-paper';
import { View, Image, WebView } from 'react-native';
const ViewRoute = (props) =>
<View style={{ flex: 1, marginTop: 40 }}>
{/* --------- This text field does not get updated -------------*/}
<Text>connected: {props.connected ? 'true' : 'false'}</Text>
{/* --------- This text field is not shown at all ------------*/}
<Text>
{props.connected.toString()}
</Text>
<Button icon="camera" mode="contained" onPress={props.setUnConnected}>
Press me
</Button>
<View style={{ height: 400, width: 400 }}>
<WebView
source={{ uri: 'https://stackoverflow.com/' }}
style={{ marginTop: 40 }}
// onLoad={() => this.setState({ connected: true })}
/>
</View>
</View>
const SettingsRoute = () => <Text>Settings</Text>;
const HelpRoute = () => <View></View>
export default class MyNavi extends React.Component {
constructor(props, context) {
super(props, context);
this.setUnConnected = this.setUnConnected.bind(this);
}
state = {
index: 0,
routes: [
{ key: 'viewcamera', title: 'View', icon: 'remove-red-eye' },
{ key: 'viewsettings', title: 'Settings', icon: 'settings' },
{ key: 'viewhelp', title: 'How-To', icon: 'help' },
],
visible: true,
connected: false,
};
_handleIndexChange = index => { this.setState({ index }); }
setUnConnected = function() {
console.log("before: " + this.state.connected);
this.setState({ connected: !this.state.connected });
console.log("after: " + this.state.connected);
console.log("--------------");
};
_renderScene = ({ route, jumpTo }) => {
switch (route.key) {
case 'viewcamera':
return <ViewRoute jumpTo={jumpTo} connected={this.state.connected} setUnConnected={this.setUnConnected}/>; //Here you can pass data from state and function to your component
case 'viewsettings':
return <SettingsRoute jumpTo={jumpTo} />;
case 'viewhelp':
return <HelpRoute jumpTo={jumpTo} />;
}
}
render() {
return (
<BottomNavigation
navigationState={this.state}
onIndexChange={this._handleIndexChange}
renderScene={this._renderScene}
/>
);
}
}

Related

FlatList not updated if data updated

I have a FlatList with data fetched from an API. There's a button on the screen that fetches data which is changed and sets the state, but the flat list doesn't refresh. I tried setting the extraData as per docs, but it didn't help. Here are the full code and snack.
If you click the Toggle List button, the alert correctly shows the new data, but the list isn't updated.
import React, {useState} from 'react';
import { SafeAreaView, View, FlatList, StyleSheet, Text, Button } from 'react-native';
import Constants from 'expo-constants';
const DATA2 = [
{
id: 0,
title: 'D2-0'
},
{
id: 1,
title: 'D2-1'
},
{
id: 2,
title: 'D2-2'
},
];
const DATA1 = [
{
id: 0,
title: 'D1-0'
},
{
id: 1,
title: 'D1-1'
},
{
id: 2,
title: 'D1-2'
},
];
export default function App(props) {
const [data, setData]=useState(DATA1);
const [dataUsed, setDataUsed]=useState(1);
return (
<SafeAreaView style={styles.container}>
<FlatList
data={data}
renderItem={({ item }) => <MyComponent data={item} /> }
keyExtractor={item => item.id}
extraData={data}
/>
<Button title="Toggle Data" onPress={() => {
let newData = dataUsed === 1 ? DATA2 : DATA1;
setDataUsed(dataUsed === 1 ? 2: 1);
alert(JSON.stringify(newData));
setData(newData);
}} />
</SafeAreaView>
);
}
class MyComponent extends React.Component {
constructor(props){
super(props);
this.state = {data: props.data};
}
render() {
return <Text>{this.state.data.title}</Text>;
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
marginTop: Constants.statusBarHeight,
padding: 50
}
});
<div data-snack-id="SkDYPf4wH" data-snack-platform="web" data-snack-preview="true" data-snack-theme="light" style="overflow:hidden;background:#fafafa;border:1px solid rgba(0,0,0,.08);border-radius:4px;height:505px;width:100%"></div>
<script async src="https://snack.expo.io/embed.js"></script>
I think you missed the reflection of the state.
Once you set the state, it could be reflected next time.
Do I think you need to use the Hook.
Please try to use it.
import React, {useState, useEffect} from 'react';
... ... ...
export default function App(props) {
const [data, setData]=useState(DATA1);
const [dataUsed, setDataUsed]=useState(1);
useEffect(()=>{
let newData = dataUsed === 1 ? DATA2 : DATA1;
setData(newData);
},[setData, dataUsed]);
return (
<SafeAreaView style={styles.container}>
<FlatList
data={data}
renderItem={({ item }) => <MyComponent data={item} /> }
keyExtractor={item => item.id}
extraData={data}
/>
<Button title="Toggle Data" onPress={() => {
setDataUsed(dataUsed === 1 ? 2: 1);
alert(JSON.stringify(newData));
}} />
</SafeAreaView>
);
}
And for the component.
class MyComponent extends React.Component {
constructor(props){
super(props);
this.state = {data: props.data};
}
componentDidUpdate(prevProps){
if( prevProps.data !== this.props.data ){
this.setData();
}
}
setData = ()=>{
this.setState({
data: this.props.data,
});
}
Render () {
return <Text>{this.state.data.title}</Text>;
}
Change MyComponent code like this
class MyComponent extends React.Component {
render() {
return <Text>{this.props.data.title}</Text>;
}
}
Your constructor code is actually useless.

FlatList renderItem not being highlighted when clicked the first time

Basically, I'm trying to setup a Flatlist in which multiple values can be selected.
My problem is with the styling of elements, when clicked the first time they don't get highlighted but when clicked the 2nd time they get highlighted.
FlatList Code
renderRow = ({item}) => (
<RowItem data={item} />
)
data = [
{
value: 'element1'
},
{
value: 'element2'
}
]
render(){
return (
<FlatList
data={this.data}
renderItem={this.renderRow}
keyExtractor={(item, index) => item + index}/>
)
}
RowItem Code
export default class RowItem extends React.Component {
state = {
isElementActive: false,
}
highlightElement = () => {
this.setState(prevState => ({
isElementActive: !prevState.isElementActive
}))
}
render() {
return (
<TouchableOpacity
activeOpacity={0.7}
onPress={this.highlightElement}
style={[styles.container, this.state.isElementActive ? styles.activeContainer : styles.inactiveContainer]}>
<Text>{this.props.data.value}</Text>
</TouchableOpacity>
)
}
}
const styles = Stylesheet.create({
container: {
height: 100,
width: 300,
backgroundColor: 'red',
},
activeContainer: {
opacity: 0.7,
},
inactiveContainer: {
opacity: 1,
}
});
When clicking on the element once, the value of the isElementActive returns true (when I console.log it) but the styling "activeContainer" does not apply. However, when I click it again, the styling applies even though the value of isElementActive then becomes false.
By default the value starts off as false, and they are not highlighted (i.e. have opacity of 1) and for this reason I'm kind of confused when clicked the first time, the value of isElementActive changes but the styling does not apply.
I was able to make it work with setOpacityTo after the setState.
Working example: https://snack.expo.io/SJNSKQPIB
import React from 'react';
import {TouchableOpacity, FlatList, StyleSheet, Text} from 'react-native';
type State = {
active: boolean;
};
type Props = {
value: string;
};
class RowItem extends React.Component<Props, State> {
state = {
active: null,
};
ref = null;
highlightElement = () => {
this.setState(
prevState => ({
active: !prevState.active,
}),
() => {
this.ref.setOpacityTo(this.state.active ? 0.7 : 1);
},
);
};
render() {
return (
<TouchableOpacity
ref={ref => (this.ref = ref)}
onPress={this.highlightElement}
style={[styles.container]}>
<Text>{this.props.value}</Text>
</TouchableOpacity>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
height: 100,
backgroundColor: 'red',
},
});
export default class App extends React.Component {
data = [
{
value: 'element1',
},
{
value: 'element2',
},
];
render() {
return (
<FlatList
keyExtractor={(_, index) => index.toString()}
data={this.data}
renderItem={({item}) => <RowItem value={item.value} />}
/>
);
}
}

Google.logInAsync function for OAuth not doing anything in React Native

Google.logInAsync function which is supposed to used for OAuth in React Native, is not giving any response, or is stuck. Take a look at my code, from line 14 to 36. This signIn function is calling Google.logInAsync and is stuck there. No error, nothing. How ever when I press the button again, and the signIn function gets called again, an error is passed: Error: Cannot start a new task while another task is currently in progress: Get Auth
This is my code currently. It shows a label " Sign In With Google" and a Button on the screen. Tapping on the button starts this.signIn funtion, prints "Started logInAsync" on the debugger screen, but theGoogle.logInAsync never completes, no errors are thrown anywhere. console.log('Completed logInAsync') never gets executed!
import {Google} from "expo"
...
console.log('Starting logInAsync')
const result = await Google.logInAsync({
androidClientId:
"<CLIENT_ID>",
scopes: ["profile", "email"]
})
console.log('Completed logInAsync')
that gave an error saying install "expo-google-app-auth"
I installed that module and then changed the import and the function
import * as Google from "expo-google-app-auth"
...
console.log('Starting logInAsync')
const result = await Google.logInAsync({
...
})
console.log('Completed logInAsync')
And after there,
import { StyleSheet, Text, View, Image, Button } from "react-native"
import * as Google from "expo-google-app-auth"
export default class App extends React.Component {
constructor(props) {
super(props)
this.state = {
signedIn: false,
name: "",
photoUrl: ""
}
}
signIn = async () => {
try {
console.log('Starting logInAsync')
const result = await Google.logInAsync({
androidClientId:
"860657237026-jfosg5hu52u1vedclccs1vgihghva534.apps.googleusercontent.com",
scopes: ["profile", "email"]
})
console.log('Completed logInAsync')
if (result.type === "success") {
this.setState({
signedIn: true,
name: result.user.name,
photoUrl: result.user.photoUrl
})
} else {
console.log("Cancelled!")
}
} catch (e) {
console.log("Error: ", e)
}
}
render() {
return (
<View style={styles.container}>
{this.state.signedIn ? (
<LoggedInPage name={this.state.name} photoUrl={this.state.photoUrl} />
) : (
<LoginPage signIn={this.signIn} />
)}
</View>
)
}
}
const LoginPage = props => {
return (
<View>
<Text style={styles.header}>Sign In With Google</Text>
<Button title="Sign in with Google" onPress={() => props.signIn()} />
</View>
)
}
const LoggedInPage = props => {
return (
<View style={styles.container}>
<Text style={styles.header}>Welcome:{props.name}</Text>
<Image style={styles.image} source={{ uri: props.photoUrl }} />
</View>
)
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#fff",
alignItems: "center",
justifyContent: "center"
},
header: {
fontSize: 25
},
image: {
marginTop: 15,
width: 150,
height: 150,
borderColor: "rgba(0,0,0,0.2)",
borderWidth: 3,
borderRadius: 150
}
})
No error occur in this code, except if you press the SignIn button twice. I am on the latest version of Node, React-Native and Expo as of now.

Mapping over data after fetching nested objects

Hello guys so i have component homescreen which i am fetching data inside and, the data i am getting contains some objects that has arrays inside, so i want to push all that arrays and data inside my state otherDetails key .
the data i am getting looks like this
{
id: 5,
url: "http://www.tvmaze.com/shows/5/true-detective",
name: "True Detective",
type: "Scripted",
language: "English",
genres: [
"Drama",
"Crime",
"Thriller"
],
status: "To Be Determined",
runtime: 60,
premiered: "2014-01-12",
officialSite: "http://www.hbo.com/true-detective",
schedule: {
time: "21:00",
days: [
"Sunday"
]
},
rating: {
average: 8.2
},
weight: 97,
network: {
id: 8,
name: "HBO",
country: {
name: "United States",
code: "US",
timezone: "America/New_York"
}
},
webChannel: null,
externals: {
tvrage: 31369,
thetvdb: 270633,
imdb: "tt2356777"
},
image: {
medium: "http://static.tvmaze.com/uploads/images/medium_portrait/178/445621.jpg",
original: "http://static.tvmaze.com/uploads/images/original_untouched/178/445621.jpg"
},
summary: "<p>Touch darkness and darkness touches you back. <b>True Detective</b> centers on troubled cops and the investigations that drive them to the edge. Each season features a new cast and a new case.</p>",
now what i am trying to do inside home screen i have my state with the object key otherDetails which i am trying to get genres language network schedule and summary so i am not sure what is happening wrong
this is my HomeScreen.js
import React, {Component} from 'react';
const axios = require('axios');
import Card from '../Components/Card/card';
import {
View,
Text,
Button,
Image,
ScrollView,
ActivityIndicator,
} from 'react-native';
import DetailsScreen from './detailsScreen';
import DetailedCard from '../Components/DetailedCard/DetailedCard';
export default class HomeScreen extends React.Component {
state = {
title: [],
image: [],
rating: [],
otherDetails:[{
genres:[],
schedule:[],
language:'',
network:[],
summary:'',
} ],
isLoading: true,
};
componentDidMount() {
this.getData();
}
getData = () => {
const requestUrls = Array.from({length: 9}).map(
(_, idx) => `http://api.tvmaze.com/shows/${idx + 1}`,
);
const handleResponse = data => {
const shows = data.map(show => show.data);
this.setState({
isLoading: false,
title: shows.map(show => show.name),
image: shows.map(show => show.image.medium),
rating: shows.map(show => show.rating.average),
otherDetails:shows.map((show,index)=>{
return [
show.genres[index],
show.schedule[index],
show.language[index],
show.network[index],
show.summary[index],
];
}),
});
};
const handleError = error => {
this.setState({
isLoading: false,
});
};
console.log(this.state.otherDetails.genres);
Promise.all(requestUrls.map(url => axios.get(url)))
.then(handleResponse)
.catch(handleError);
};
render() {
const {isLoading, title, image, rating, otherDetails} = this.state;
if (isLoading) {
return <ActivityIndicator size="large" color="#0000ff" />;
}console.log(this.state);
return (
<View style={{flex: 1, alignItems: 'center', justifyContent: 'center'}}>
<View style={{backGroundColor: 'red'}} />
<ScrollView style={{flex: 1}}>
<Card
title={this.state.title}
rating={this.state.rating}
source={this.state.image}
navigation = {this.props.navigation}
/>
</ScrollView>
<Text>here images</Text>
</View>
);
}
}
any help would be nice thank you in advanced ...!
Storing the response from tvmaze as an array instead of trying to map all the values to keys would make your life a bit easier.. Something like this should work:
import axios from 'axios'
import React from 'react'
import { ActivityIndicator, ScrollView, Text, View } from 'react-native'
import Card from '../Components/Card/card'
export default class HomeScreen extends React.Component {
state = {
shows: [],
isLoading: true
}
componentDidMount () {
this.getData()
}
getData = () => {
const requestUrls = Array.from({length: 9}).map(
(_, idx) => `http://api.tvmaze.com/shows/${idx + 1}`
)
const handleResponse = data => {
console.log(data)
this.setState({
isLoading: false,
shows: data
})
}
const handleError = error => {
console.log(error)
this.setState({
isLoading: false
})
}
Promise.all(requestUrls.map(url => axios.get(url)))
.then(handleResponse)
.catch(handleError)
}
render () {
const {isLoading, shows} = this.state
if (isLoading) {
return <ActivityIndicator size='large' color='#0000ff' />
}
console.log(this.state)
return (
<View style={{flex: 1, alignItems: 'center', justifyContent: 'center'}}>
<View style={{backGroundColor: 'red'}} />
<ScrollView style={{flex: 1}}>
{shows.length && shows.map(show => (
<Card key={show.data.id}
title={show.data.name}
{/*navigation={this.props.navigation}*/}
/>
))}
</ScrollView>
<Text>here images</Text>
</View>
)
}
}

React native Invariant Violation: Element type is invalid: expected a string (for built-in components) or a class/function

I'm getting this error.
Invariant Violation: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.
Check the render method of ListScreen.
wonder what's the issue. I would appreciate your help. thanks
ListScreen.js
import React, { Component } from 'react'
import { Alert, Dimensions, Platform, View } from 'react-native'
import { Button, Header, Icon, Input, Item, Left, Right, Text } from 'native-base'
import UltimateListView from 'react-native-ultimate-listview'
// import { UltimateListView } from '../lib/index'
import styles from './Styles/ListScreenStyles'
import LoadingSpinner from '../Components/LoadingSpinner'
import ControlTab from '../Components/ControlTab'
import FlatListItem from '../Components/FlatListItem'
import FlatListGrid from '../Components/FlatListGrid'
const { width, height } = Dimensions.get('window')
export default class ListScreen extends Component {
constructor(props) {
super(props)
this.state = {
layout: 'list',
text: ''
}
}
onFetch = async (page = 1, startFetch, abortFetch) => {
try {
// This is required to determinate whether the first loading list is all loaded.
let pageLimit = 24
if (this.state.layout === 'grid') pageLimit = 60
const skip = (page - 1) * pageLimit
// Generate dummy data
let rowData = Array.from({ length: pageLimit }, (value, index) => `item -> ${index + skip}`)
// Simulate the end of the list if there is no more data returned from the server
if (page === 10) {
rowData = []
}
// Simulate the network loading in ES7 syntax (async/await)
await this.sleep(2000)
startFetch(rowData, pageLimit)
} catch (err) {
abortFetch() // manually stop the refresh or pagination if it encounters network error
console.log(err)
}
}
onChangeLayout = (event) => {
this.setState({ text: '' })
switch (event.nativeEvent.selectedSegmentIndex) {
case 0:
this.setState({ layout: 'list' })
break
case 1:
this.setState({ layout: 'grid' })
break
default:
break
}
}
onChangeScrollToIndex = (num) => {
this.setState({ text: num })
let index = num
if (this.state.layout === 'grid') {
index = num / 3
}
try {
this.listView.scrollToIndex({ viewPosition: 0, index: Math.floor(index) })
} catch (err) {
console.warn(err)
}
}
onPressItem = (type, index, item) => {
Alert.alert(type, `You're pressing on ${item}`)
}
sleep = time => new Promise(resolve => setTimeout(() => resolve(), time))
renderItem = (item, index, separator) => {
if (this.state.layout === 'list') {
return (
<FlatListItem item={item} index={index} onPress={this.onPressItem} />
)
} else if (this.state.layout === 'grid') {
return (
<FlatListGrid item={item} index={index} onPress={this.onPressItem} />
)
}
return null
}
renderControlTab = () => (
<ControlTab
layout={this.state.layout}
onChangeLayout={this.onChangeLayout}
/>
)
renderHeader = () => (
<View>
<View style={styles.header}>
<Text style={{ textAlign: 'center' }}>I am the Header View, you can put some Instructions or Ads Banner here!
</Text>
</View>
<View style={styles.headerSegment}>
<Left style={{ flex: 0.15 }} />
{this.renderControlTab()}
<Right style={{ flex: 0.15 }} />
</View>
</View>
)
renderPaginationFetchingView = () => (
<LoadingSpinner height={height * 0.2} text="loading..." />
)
render() {
return (
<View style={styles.container}>
<Header searchBar rounded>
<Item style={{ backgroundColor: 'lightgray', borderRadius: 5 }}>
<Icon name="ios-search" />
<Input placeholder="Search" onChangeText={this.onChangeScrollToIndex} value={this.state.text} />
</Item>
</Header>
<UltimateListView
ref={ref => this.listView = ref}
key={this.state.layout} // this is important to distinguish different FlatList, default is numColumns
onFetch={this.onFetch}
keyExtractor={(item, index) => `${index} - ${item}`} // this is required when you are using FlatList
refreshableMode="advanced" // basic or advanced
item={this.renderItem} // this takes three params (item, index, separator)
numColumns={this.state.layout === 'list' ? 1 : 3} // to use grid layout, simply set gridColumn > 1
// ----Extra Config----
displayDate
header={this.renderHeader}
paginationFetchingView={this.renderPaginationFetchingView}
// sectionHeaderView={this.renderSectionHeaderView} //not supported on FlatList
// paginationFetchingView={this.renderPaginationFetchingView}
// paginationAllLoadedView={this.renderPaginationAllLoadedView}
// paginationWaitingView={this.renderPaginationWaitingView}
// emptyView={this.renderEmptyView}
// separator={this.renderSeparatorView}
// new props on v3.2.0
arrowImageStyle={{ width: 20, height: 20, resizeMode: 'contain' }}
dateStyle={{ color: 'lightgray' }}
refreshViewStyle={Platform.OS === 'ios' ? { height: 80, top: -80 } : { height: 80 }}
refreshViewHeight={80}
/>
</View>
)
}
}
Navigation.js
import { StackNavigator } from 'react-navigation'
import LaunchScreen from '../Containers/LaunchScreen'
import ListScreen from '../Containers/ListScreen'
import styles from './Styles/NavigationStyles'
// Manifest of possible screens
const PrimaryNav = StackNavigator({
LaunchScreen: { screen: LaunchScreen },
ListScreen: { screen: ListScreen }
}, {
// Default config for all screens
headerMode: 'none',
initialRouteName: 'ListScreen',
navigationOptions: {
headerStyle: styles.header
}
})
export default PrimaryNav
As mentioned in the docs of react-native-ultimate-listview, there is a breaking change and you need to the import react-native-ultimate-listview as
import { UltimateListView } from 'react-native-ultimate-listview'

Resources