Algolia and Hooks in React Native can't navigate to an other page - react-native

I'm using algolia with react Native and Expo, I make a connectInfiniteHits and i want to navigate to an other page when the user press a hit, i have the following code:
import React from "react";
import { StyleSheet, Text, View, FlatList, Image, TouchableOpacity, AsyncStorage } from "react-native";
import { connectInfiniteHits } from "react-instantsearch-native";
import PropTypes from 'prop-types';
import { useNavigation } from '#react-navigation/native';
const navigation = (id) => {
const navigation = useNavigation();
AsyncStorage.setItem("RepID", id);
navigation.navigate("RepProfile");
}
const InfiniteHitsRep = ({ hits, hasMore, refine }) => (
<View style={styles.container}>
<FlatList
data={hits}
onEndReached={() => hasMore && refine()}
onEndReachedThreshold={0}
keyExtractor={item => item.objectID}
initialNumToRender={10}
ItemSeparatorComponent={() => <View style={styles.separator} />}
renderItem={({ item }) => (
<TouchableOpacity onPress={() => navigation(item.rep_id)} style={{ flexDirection: 'row', alignItems: 'center' }}>
<Image style={styles.image} source={{ uri: item.rep_img_url }} />
<Text style={{ flex: 3 }}>{item.rep_title} {item.rep_first_name} {item.rep_last_name}</Text>
<Image style={styles.image} source={{ uri: item.house_img_url }} />
</TouchableOpacity>
)}
/>
</View>
)
);
InfiniteHitsRep.propTypes = {
hits: PropTypes.arrayOf(PropTypes.object).isRequired,
hasMore: PropTypes.bool.isRequired,
refine: PropTypes.func.isRequired,
};
export default connectInfiniteHits(InfiniteHitsRep);
const styles = StyleSheet.create({
container: {
padding: 16,
},
separator: {
marginTop: 16,
marginBottom: 16,
height: 1,
backgroundColor: "#DDDDDD",
},
image: {
flex: 1,
width: 50,
height: 50,
borderRadius: 5,
backgroundColor: 'white',
resizeMode: 'contain',
}
});
And when I press a hit I have this error message:
[![```
Error: Invalid hook call. Hooks can only be called inside of the body of a function component.
[1]: https://i.stack.imgur.com/yDYRg.png

Hooks can be used inside a function component only
Change your code to this
import React from "react";
import {
StyleSheet,
Text,
View,
FlatList,
Image,
TouchableOpacity,
AsyncStorage,
} from "react-native";
import { connectInfiniteHits } from "react-instantsearch-native";
import PropTypes from "prop-types";
import { useNavigation } from "#react-navigation/native";
const InfiniteHitsRep = ({ hits, hasMore, refine }) => {
const navigation = useNavigation(); // Call hook here
const navigation = (id) => {
AsyncStorage.setItem("RepID", id);
navigation.navigate("RepProfile"); // Use Here
};
return (
<View style={styles.container}>
<FlatList
data={hits}
onEndReached={() => hasMore && refine()}
onEndReachedThreshold={0}
keyExtractor={(item) => item.objectID}
initialNumToRender={10}
ItemSeparatorComponent={() => <View style={styles.separator} />}
renderItem={({ item }) => (
<TouchableOpacity
onPress={() => navigation(item.rep_id)}
style={{ flexDirection: "row", alignItems: "center" }}
>
<Image style={styles.image} source={{ uri: item.rep_img_url }} />
<Text style={{ flex: 3 }}>
{item.rep_title} {item.rep_first_name} {item.rep_last_name}
</Text>
<Image style={styles.image} source={{ uri: item.house_img_url }} />
</TouchableOpacity>
)}
/>
</View>
);
};
InfiniteHitsRep.propTypes = {
hits: PropTypes.arrayOf(PropTypes.object).isRequired,
hasMore: PropTypes.bool.isRequired,
refine: PropTypes.func.isRequired,
};
export default connectInfiniteHits(InfiniteHitsRep);
const styles = StyleSheet.create({
container: {
padding: 16,
},
separator: {
marginTop: 16,
marginBottom: 16,
height: 1,
backgroundColor: "#DDDDDD",
},
image: {
flex: 1,
width: 50,
height: 50,
borderRadius: 5,
backgroundColor: "white",
resizeMode: "contain",
},
});

Related

Try to render data from Api using Hook in React-Native

I'm new here and in react-native.
I want render some data from IMDB Api with the "hook" method.
So I try to render data in a flatlist, I can see in the console that the data is retrieved properly in a jSon format witch is a good thing but when I open my app I don't see any rendering on the screen.
I try to use the 'Hook' method and not the 'classes' and I'm pretty sure that I don't use properly the useState method.
So any help or advices are welcome.
My code:
App
import React, { useState } from "react";
import {
View,
Text,
StyleSheet,
Button,
TextInput,
FlatList,
} from "react-native";
// import films from "../Helpers/filmsData";
import FilmsItem from "./FilmsItem";
import getFilmsFromApiWithSearchedText from "../Api/TMDBApi";
const Search = () => {
const [films, setFilms] = useState([]);
const _loadFilms = () => {
getFilmsFromApiWithSearchedText("White").then(
(data) => setFilms({ film: data.results }),
console.log(films)
);
};
return (
<View style={styles.container}>
<TextInput style={styles.input} placeholder="Titre du film" />
<Button
style={styles.button}
title="Rechercher"
onPress={() => _loadFilms()}
/>
<FlatList
data={setFilms.films}
keyExtractor={(item) => item.id.toString()}
renderItem={({ item }) => <FilmsItem films={item} />}
/>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
marginTop: 20,
},
input: {
marginLeft: 5,
marginRight: 5,
height: 50,
paddingLeft: 5,
borderWidth: 1,
borderColor: "#000000",
},
});
export default Search;
Api request:
// Api/TMDBApi.js
const API_TOKEN = "**************************";
const getFilmsFromApiWithSearchedText = (text) => {
const url =
"https://api.themoviedb.org/3/search/movie?api_key=" +
API_TOKEN +
"&language=en&query=" +
text;
return fetch(url)
.then((response) => response.json())
.catch((error) => console.error(error));
};
export default getFilmsFromApiWithSearchedText;
FilmItem:
import React from "react";
import { View, Text, StyleSheet, Image } from "react-native";
const FilmsItem = (props) => {
const film = props.film;
return (
<View style={styles.container}>
<Image style={styles.img} source={{ uri: "image" }} />
<View style={styles.content}>
<View style={styles.header}>
<Text style={styles.title}>{film.title}</Text>
<Text style={styles.vote}>{film.vote_average}</Text>
</View>
<View style={styles.synopsis}>
<Text style={styles.synopsysText} numberOfLines={6}>
{film.overview}
</Text>
</View>
<View style={styles.date}>
<Text style={styles.dateText}>Sorti le {film.release_date}</Text>
</View>
</View>
</View>
);
};
const styles = StyleSheet.create({
container: {
flexDirection: "row",
height: 190,
},
content: {
flex: 1,
margin: 5,
},
img: {
height: 180,
width: 120,
margin: 5,
backgroundColor: "gray",
},
header: {
flex: 3,
flexDirection: "row",
},
title: {
flex: 1,
flexWrap: "wrap",
fontWeight: "bold",
fontSize: 20,
paddingRight: 5,
},
vote: {
fontWeight: "bold",
fontSize: 20,
color: "#666666",
},
synopsis: {
flex: 7,
},
synopsysText: {
fontStyle: "italic",
color: "#666666",
},
date: {
flex: 1,
paddingBottom: 10,
},
dateText: {
textAlign: "right",
fontSize: 14,
},
});
export default FilmsItem;
const _loadFilms = () => {
getFilmsFromApiWithSearchedText("White").then(
(data) => setFilms({ film: data.results }),
console.log(films)
);
};
setFilms({ film: data.results }) will set an object, but you need an array in there.
Try to do something like this: setFilms(data.results)
use useState in this way
const _loadFilms = () => {
getFilmsFromApiWithSearchedText("White").then(
(data) => setFilms(data.results),
console.log(films)
);
};
then in Flatlist you can use like this
return (
<View style={styles.container}>
<TextInput style={styles.input} placeholder="Titre du film" />
<Button
style={styles.button}
title="Rechercher"
onPress={() => _loadFilms()}
/>
<FlatList
data={films}
keyExtractor={(item) => item.id.toString()}
renderItem={({ item }) => <FilmsItem films={item} />}
/>
</View>
);

how to use the state hook for dynamically created components in react native

I am trying to do is use useState for dynamically created components in React. In the code below I am, rendering the new components, but I cannot find a way to keep track of their state like I did for the hardcoded components. The new components are rendered when the user creates a new "post", causing new "posts" to be generated.
return (
{
results.map( (eachPost) =>
{ const [status, setStatus] = React.useState(true); },
<TouchableOpacity>
<Card>
<Text>
{JSON.parse(eachPost).title}
</Text>
<Collapsible collapsed = {status}>
{JSON.parse(eachPost).content}
</Collapsible>
</Card>
</TouchableOpacity>
)
}
)
UPDATE: I need to know how I can re-render the page
import * as React from 'react';
import { StyleSheet, Button, TextInput, Image, TouchableOpacity } from 'react-native';
import EditScreenInfo from '../components/EditScreenInfo';
import { Text, View } from '../components/Themed';
import { NavigationContainer } from '#react-navigation/native';
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
import { Card } from 'react-native-elements';
import Collapsible from 'react-native-collapsible';
import Accordion from 'react-native-collapsible/Accordion';
import { CardStyleInterpolators } from '#react-navigation/stack';
import AsyncStorage from '#react-native-community/async-storage';
import { useState, useCallback } from 'react';
import Post from './Post'
import RenderToLayer from 'material-ui/internal/RenderToLayer';
import { useForceUpdate } from './useForceUpdate'
async function createNewPost (titleAndContent : string){
const post = {titleAndContent_: titleAndContent}
try {
await AsyncStorage.setItem('post' + Math.floor(100000 + Math.random() * 900000), JSON.stringify(post))
} catch (e) {
console.log(e)
}
//console.log(newPosts)
}
export default function NewsScreen({ navigation }: { navigation: any }) {
const [status, setStatus] = React.useState(true);
const [status2, setStatus2] = React.useState(true);
const [status3, setStatus3] = React.useState(true);
const [renderedData, setRenderedData] = React.useState(new Array<string>());
const [input, setInput] = React.useState('Please enter the details of the post in the format of title,content');
const [, forceUpdate] = useState();
const getData = async () => {
try {
const keys = await AsyncStorage.getAllKeys();
const result = await AsyncStorage.multiGet(keys);
console.log(result)
return result;
} catch (e) {
console.log(e);
}
};
async function parseData() {
const payments = await getData();
if (payments) {
const res = payments
//.filter((e: any[]) => e[1] && e.includes('{'))
//.map((e: any[]) => e[1]);
setRenderedData(res);
console.log(res)
}
return renderedData;
}
const results: string[] = []
renderedData.forEach( (eachPost) => {
if ((/\{"title.*}/g.test(eachPost[1]))) results.push(eachPost[1])
})
console.log(results)
React.useEffect(() => {
if (renderedData.length === 0) {
parseData();
}
forceUpdate
},[]);
return (
<View style={styles.container}>
<Text style={{ fontSize: 25}}>News</Text>
<View style = {{flexDirection: "row"}}>
<TextInput
style={{ height: 40, width: 700, borderColor: 'gray', borderWidth: 1 }}
value = {input}
onChangeText={text=>setInput(text)}
/>
<Button
onPress={()=> createNewPost(input)}
title="Add post"
color="blue"
accessibilityLabel="A button to allow the admin to create a new post"
/>
<Button
onPress = {useForceUpdate()}
title="submit"
/>
</View>
<View>
{
results.map( (eachPost) =>
<Post titleAndContent={JSON.parse(eachPost)}/>
)
}
<TouchableOpacity onPress={() => setStatus(!status)}>
<Card>
<Text>
Moore Park Lift Outage
</Text>
<Image
source={{
uri: 'https://i.imgur.com/Etr5xBn.png'
}}
style={{width: 20, height: 20, marginLeft: 10}}
>
</Image>
<Collapsible collapsed = {status}>
<Text style={{fontWeight: 'bold'}}>
UPDATED 6 Aug 09:30 {'\n'}
Details: Ongoing {'\n'}
Lift 2 at Moore Park Light Rail is temporarily out of service. For assistance, ask staff.. {'\n'}
</Text>
<Image
source={{
uri: 'https://svg-clipart.com/svg/blue/PGaAIh0-blue-wheelchair-vector.svg',
}}
style={{width: 70, height: 90, marginTop: 30}}
>
</Image>
</Collapsible>
</Card>
</TouchableOpacity>
<TouchableOpacity onPress={() => setStatus2(!status2)}>
<Card>
<Text>Dulwich Hill Line running slow</Text>
<Image
source={{
uri: 'https://i.imgur.com/iNjXQMW.png'
}}
style={{width: 20, height: 20, marginLeft: 10}}
>
</Image>
<Collapsible collapsed = {status2}>
<Text>
The Dulwich Hill Line is running slow due to track-work being conducted between Lilyfield and Rozelle Bay
</Text>
</Collapsible>
</Card>
</TouchableOpacity>
<TouchableOpacity onPress={() => setStatus3(!status3)}>
<Card >
<Text>Extra services running</Text>
<Image
source={{
uri: 'https://imgur.com/Etr5xBn'
}}
style={{width: 20, height: 20, marginLeft: 10}}
>
</Image>
<Image
source={{
uri: 'https://i.imgur.com/Etr5xBn.png'
}}
style={{width: 20, height: 20, marginLeft: 10}}
>
</Image>
<Collapsible collapsed = {status3}>
<Text>
Extra services will be running this week to help students get back to school
</Text>
</Collapsible>
</Card>
</TouchableOpacity>
</View>
<View style={styles.button}>
<Button
onPress={() => navigation.navigate('HomeScreen')}
title="Go back"
color="blue"
accessibilityLabel="A button to click so that you can go back to the home page"
/>
</View>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'flex-start',
justifyContent: 'flex-start',
flexDirection: 'column',
},
title: {
fontSize: 20,
fontWeight: 'bold',
alignItems: 'center',
justifyContent: 'center',
},
separator: {
marginVertical: 30,
height: 1,
width: '80%',
},
button: {
margin: 10,
flexDirection: 'row',
},
news:{
flexDirection:'column',
backgroundColor: 'white',
},
eachnews:{
margin: 500,
fontWeight: 'bold',
alignItems: 'flex-start',
justifyContent: 'flex-start',
},
textnews:{
fontSize: 20,
},
});
I think you need more knowledge related to basics of react.
You need a Post component
Post.js
export default (props) => {
const [status, setStatus] = useState();
return (<TouchableOpacity>
<Card>
<Text>
{props.title}
</Text>
<Collapsible collapsed = {status}>
{props.content}
</Collapsible>
</Card>
</TouchableOpacity>);
};
When u call Post
App.js
import Post from './Post.js'
export default App = ()
{
const result = [];
return (
results.map( (eachPost) =>{
const eachPost = JSON.parse(eachPost);
return (<Post title={eachPost.title} content={eachPost.content})/>)
}
}
)

Sending data to another component with (React Native Navigation)

I want to send basic data from Home.js component to details.js component.
My home.js
import React, { useState, useEffect } from 'react'
import { View, TouchableHighlight, Image, FlatList, ActivityIndicator, Text, StyleSheet } from 'react-native'
function HomeScreen({ navigation }) {
const [isLoading, setIsLoading] = useState(true)
const [dataSource, setDataSource] = useState([])
useEffect(() => {
fetch('http://www.json-generator.com/api/json/get/bVxGaxSSgi?indent=2')
.then((response) => response.json())
.then((responseJson) => {
setIsLoading(false)
setDataSource(responseJson)
})
.catch((error) => {
alert(error)
});
})
if (isLoading) {
return (
<View style={{ flex: 1, padding: 20 }}>
<ActivityIndicator />
</View>
)
}
return (
<View style={{ flex: 1, paddingTop: 20, paddingHorizontal: 20 }}>
<FlatList
data={dataSource}
renderItem={({ item }) =>
<TouchableHighlight onPress={() => navigation.navigate('Details',{text:'alperen'})} underlayColor="white">
<View style={styles.button}>
<View style={styles.div}>
<View style={styles.inlineDiv}>
<Image source={{ uri: 'https://source.unsplash.com/random/900&#x2715700/?fruit' }} style={styles.pic} />
<Text>{item.name}, {item.about}</Text>
</View>
</View>
</View>
</TouchableHighlight>
}
keyExtractor={({ _id }, index) => _id}
/>
</View>
)
}
export default HomeScreen
const styles = StyleSheet.create({
pic: {
width: '100%',
height: 200,
borderRadius: 20,
},
div: {
shadowColor: "#fff",
shadowOffset: {
width: 0,
height: 1,
},
shadowOpacity: 0.20,
shadowRadius: 50,
elevation: 0,
marginBottom: 10
},
inlineDiv: {
padding: 5,
},
button: {
alignItems: 'center',
},
});
This is my details.js component
import React, { useEffect } from 'react'
import { View, Text } from 'react-native'
function DetailsScreen( navigation ) {
useEffect(() => {
alert(navigation.text)
})
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text></Text>
</View>
);
}
export default DetailsScreen
I want to go to the other page and at the same time I want to send and print the data. This code is currently returning undefined. How Can I send data ? Probably I can use props but I don't know usage.
Change
function DetailsScreen( navigation ) {
useEffect(() => {
alert(navigation.text)
})
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text></Text>
</View>
);
}
to
function DetailsScreen({navigation}) {
useEffect(() => {
alert(navigation.state.params.text)
})
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text></Text>
</View>
);
}
And try
In first screen
<TouchableHighlight onPress={() => navigation.navigate('Details',{item})} underlayColor="white">
In next screen you can get data
this.props.navigation.state.params.item
Example:
<Image source={this.props.navigation.state.params.item.img}/>
<Text>{this.props.navigation.state.params.item.text}</Text>
Sending data operation is success but details page is not working. I looked 'react-navigation documentation ' (https://reactnavigation.org/docs/en/params.html). There is a keyword ('route') we have to use it.
function DetailsScreen({ route }) {
const { text } = route.params;
useEffect(() => {
var a = JSON.stringify(text)
alert(a)
})
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text></Text>
</View>
);
}
I tried this code and its working success.

Modal and FlatList

i work on my first react-native project and its also my firts javascript work. I want at least a news-app with own database informations. The backend is already finish. Now im in struggle with the app- i want an Popup with Modal with informations from my api like news_image, news_content and news_title. The News are in the FlatList and now i want to click on a item to show the content in an modal popup. so, here is my code where im struggle. i get always an error. so how can i fix this problem? tanks a lot!
import React from "react";
import {
AppRegistry,
FlatList,
Image,
Platform,
ScrollView,
StyleSheet,
Text,
TouchableOpacity,
View,
ActivityIndicator,
ListView,
YellowBox,
Alert,
TextInput
} from "react-native";
import { WebBrowser } from "expo";
import Button from "react-native-button";
import Modal from "react-native-modalbox";
import Slider from "react-native-slider";
import { MonoText } from "../components/StyledText";
export default class NewsFeed extends React.Component {
static navigationOptions = {
title: "HomeScreen"
};
constructor(props) {
super(props);
this.state = {
isLoading: true
};
YellowBox.ignoreWarnings([
"Warning: componentWillMount is deprecated",
"Warning: componentWillReceiveProps is deprecated"
]);
}
FlatListItemSeparator = () => {
return (
<View
style={{
height: 0.5,
width: "100%",
backgroundColor: "#000"
}}
/>
);
};
webCall = () => {
return fetch("http://XXXXXXXXXXXX.com/connection.php")
.then(response => response.json())
.then(responseJson => {
this.setState(
{
isLoading: false,
dataSource: responseJson
},
function() {
// In this block you can do something with new state.
}
);
})
.catch(error => {
console.error(error);
});
};
onClose() {
console.log("Modal just closed");
}
onOpen() {
console.log("Modal just opened");
}
onClosingState(state) {
console.log("the open/close of the swipeToClose just changed");
}
componentDidMount() {
this.webCall();
}
render() {
if (this.state.isLoading) {
return (
<View
style={{ flex: 1, justifyContent: "center", alignItems: "center" }}
>
<ActivityIndicator size="large" />
</View>
);
}
return (
<View style={styles.MainContainer}>
<FlatList
data={this.state.dataSource}
ItemSeparatorComponent={this.FlatListItemSeparator}
renderItem={({ item }) => (
<View style={{ flex: 1, flexDirection: "row" }}>
<Image
source={{ uri: item.news_image }}
style={styles.imageView}
/>
<Text
onPress={() => this.refs.modal.open()}
style={styles.textView}
>
{item.news_title}
{"\n"}
<Text style={styles.textCategory}>{item.author}</Text>
</Text>
<Text style={styles.textViewDate}>{item.created_at}</Text>
<Modal
style={[styles.modal]}
position={"bottom"}
ref={"modal"}
swipeArea={20}
>
<ScrollView>
<View style={{ width: "100%", paddingLeft: 10 }}>
{item.news_content}
</View>
</ScrollView>
</Modal>
</View>
)}
keyExtractor={(item, index) => index.toString()}
/>
</View>
);
}
}
const styles = StyleSheet.create({
MainContainer: {
justifyContent: "center",
flex: 1,
margin: 5
},
imageView: {
width: "25%",
height: 100,
margin: 7,
borderRadius: 7
},
textView: {
width: "100%",
height: "100%",
textAlignVertical: "center",
padding: 10,
fontSize: 20,
color: "#000"
},
textViewDate: {
width: "30%",
textAlignVertical: "center",
padding: 15,
color: "#afafaf"
},
textCategory: {
color: "#d3d3d3",
fontSize: 12
},
modal: {
justifyContent: "center",
alignItems: "center",
height: "90%"
}
});
Check the code below and compare it with your code.
I am not sure where your error is located or what your exact error is, but you can check the example code below, which is similar to yours, for comparison.
I am using 'Axios' over fetch() because of the automatic transformation to JSON and some other beneficial stuff.
npm install --save axios
Code:
import React, { Component } from 'react'
import {
ActivityIndicator,
FlatList,
Image,
ScrollView,
Text,
TouchableOpacity,
View
} from 'react-native';
import Axios from 'axios';
import Modal from "react-native-modalbox";
export default class NewsFeed extends Component {
constructor(props) {
super(props);
this.state = {
dataSource: [],
selectedIndex : -1
}
}
componentDidMount = () => {
Axios.get('<URL>')
.then(response => {
const { data } = response;
this.setState({dataSource : data});
}).catch(error => {
const { data } = error;
console.log(data);
});
}
_openModal = index => {
this.setState({ selectedIndex : index });
this.modalReference.open();
}
_renderSeparator = () => {
return <View style={{ flex: 1, borderBottomWidth: 0.5, borderBottomColor: '#000000' }} />
}
_renderItem = ({item, index}) => {
const {news_image, news_title, news_content, author, created_at} = item;
return <TouchableOpacity onPress={() => this._openModal(index)} >
<View style={{ flex: 1, flexDirection: 'row' }}>
<Image style={{ flex: 1, width: null, height: 200 }} source={{ uri: news_image }} />
<Text>{news_title}</Text>
<Text>{author}</Text>
<Text>{created_at}</Text>
</View>
</TouchableOpacity>;
}
render = () => {
const { dataSource, selectedIndex } = this.state;
const { news_content } = dataSource[selectedIndex];
return dataSource.length === 0 ?
<View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
<ActivityIndicator size="large" />
</View> :
<View style={styles.MainContainer}>
<FlatList
data={dataSource}
keyExtractor={(item, index) => index.toString()}
ItemSeparatorComponent={this._renderSeparator}
renderItem={this._renderItem}
/>
<Modal ref={reference => modalReference = reference}>
<ScrollView style={{ flex: 1, padding: 20 }}>
<Text>{news_content}</Text>
</ScrollView>
</Modal>
</View>
}
}
I think the issue is in modal,
Can you re-write the code like below?
return (
<View style={styles.MainContainer}>
<FlatList
data={this.state.dataSource}
ItemSeparatorComponent={this.FlatListItemSeparator}
renderItem={({ item }) => (
<View style={{ flex: 1, flexDirection: "row" }}>
<Image source={{ uri: item.news_image }} style={styles.imageView} />
<Text onPress={() => { this.setState({ item: item.news_content }, () => this.refs.modal.open()); }} style={styles.textView}>
{item.news_title}
<Text style={styles.textCategory}>{item.author}</Text>
</Text>
<Text style={styles.textViewDate}>{item.created_at}</Text>
</View>
)}
keyExtractor={(item, index) => index.toString()}
/>
<Modal
style={[styles.modal]}
position={"bottom"}
ref={"modal"}
swipeArea={20}
>
<ScrollView>
<View style={{ width: "100%", paddingLeft: 10 }}>
{this.state.item}
</View>
</ScrollView>
</Modal>
</View>
);
Only single modal is enough for popup screen.
And you can try this also,
Change your reference to
ref={ref => this.modalRef = ref}
And use like this,
this.modalRef.open()

React navigation status bar alert

I'm using react-native-status-bar-alert in combination with react-navigation.
In the latest version of react-navigation there's a problem with the height.
The height of the header is too big when the alert is active.
Anyone else experienced this issue and has a solution?
I think you should use a plugin: navigationbar-react-native
First, if you use react-navigation you should hide header-bar and use custom header-bar
export const RootStack = createStackNavigator(
{
Home: {
screen: HomeComponent,
navigationOptions: {
header: null,
},
},
},
{
initialRouteName: 'Home',
}
);
1, Install package
npm i navigationbar-react-native --save
2, Using
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,Image,
View,
TouchableOpacity,
} from 'react-native';
import NavigationBar from 'navigationbar-react-native';
const ComponentLeft = () => {
return(
<View style={{ flex: 1, alignItems: 'flex-start'}} >
<TouchableOpacity style={ {justifyContent:'center', flexDirection: 'row'}}>
<Image
source={require('./img/ic_back.png')}
style={{ resizeMode: 'contain', width: 20, height: 20, alignSelf: 'center' }}
/>
<Text style={{ color: 'white', }}>Back Home</Text>
</TouchableOpacity>
</View>
);
};
const ComponentCenter = () => {
return(
<View style={{ flex: 1, }}>
<Image
source={require('./img/ic_logo.png')}
style={{resizeMode: 'contain', width: 200, height: 35, alignSelf: 'center' }}
/>
</View>
);
};
const ComponentRight = () => {
return(
<View style={{ flex: 1, alignItems: 'flex-end', }}>
<TouchableOpacity>
<Text style={{ color: 'white', }}> Right </Text>
</TouchableOpacity>
</View>
);
};
class App extends Component {
render() {
return (
<View style={styles.container}>
<NavigationBar
componentLeft = { () => {<ComponentLeft /> }
componentCenter = { () => {<ComponentCenter /> }
componentRight = { () => {<ComponentRight /> }
navigationBarStyle= {{ backgroundColor: ''#215e79'' }}
statusBarStyle = {{ barStyle: 'light-content', backgroundColor: '#215e79' }}
/>
</View>
);
}
}
Easy create custom header bar in react native