Position component in React Native with inline styling - javascript

I'm trying to move the pizza icon to be directly right of the search bar.
Not only have I not been able to move the search pizza icon to the right of the search bar, I have not been able to move it at all.
This main pizza icon is in MainPage as :
import React, { Component } from 'react';
import { Text, View } from 'react-native';
import axios from 'axios';
import Card from './Card'
import NewCard from './NewCard'
export default class MainPage extends Component {
constructor(props) {
super(props)
this.createLibrary = this.createLibrary.bind(this)
this.state = {
librarys: []
}
}
componentDidMount() {
axios.get('http://localhost:3000/libraries')
.then(res => {
const librarys = res.data;
this.setState({ librarys: librarys });
console.log(this.state.librarys)
})
}
//Create card
createLibrary(library) {
axios.post('http://localhost:3000/libraries', { library })
.then(res => {
this.updateLibrary(library)
})
}
updateLibrary(library){
let newLibrarys = this.state.librarys.filter((f) => f.id !== library.id)
newLibrarys.unshift(library)
this.setState({
librarys: newLibrarys
})
}
render() {
return (
<View>
<NewCard
createLibrary={this.createLibrary}
style={{position: 'absolute',
left: 20,
top: 20}}
/>
<Card style={{justifyContent: 'flex-end'}} librarys={this.state.librarys}/>
</View>
);
}
}
This is the new card component:
import React, { Component } from 'react';
import { Text, View, TextInput, Dimensions } from 'react-native';
import { Header, Form, Item, Input, Icon, Button } from "native-base";
export default class MainPage extends Component {
constructor(props) {
super(props)
this.state = {
title: '',
desc: '',
markdown: '',
showHide: 'none'
}
}
submitForm = () => {
let title = this.state.title
let desc = this.state.desc
let markdown = this.state.markdown
let library = {title: title, desc: desc, markdown: markdown}
this.props.createLibrary(library)
}
showForm = () => {
this.state.showHide === 'none' ?
this.setState({showHide: 'flex'}) :
this.setState({showHide: 'none'})
}
render() {
const formStyle = {
display: this.state.showHide,
width: Dimensions.get('window').width,
height: Dimensions.get('window').height
}
return (
<View>
<Icon
name='pizza'
onPress={this.showForm}
style={{display: this.state.showHide === 'none' ? 'flex' : 'none'}}
/>
<Form style={formStyle} >
<Item>
<Input
placeholder="Title"
name="title"
onChangeText={(value) => this.setState({title: value})}
/>
</Item>
<Item>
<Input
placeholder="Description"
name="desc"
onChangeText={(value) => this.setState({desc: value})}
/>
</Item>
<Item>
<Input
placeholder="Markdown"
name="markdown"
onChangeText={(value) => this.setState({markdown: value})}
/>
</Item>
<Button
light
onPress={this.submitForm.bind(this)}
>
<Text> Submit </Text>
</Button>
</Form>
</View>
);
}
}
The search bar is in the card component:
import React, { Component } from 'react';
import { Text, View } from 'react-native';
import { Header, Form, Item, Input, Icon, Button, Accordion } from "native-base";
export default class MainPage extends Component {
constructor(props) {
super(props)
this.state = {
activeIndex: null,
search: '',
sortCards: "newest",
search: ''
}
}
render() {
var filteredCards = this.props.librarys.filter(
(library) => {
return library.title.toLowerCase().indexOf(this.state.search.toLowerCase()) !== -1 || library.desc.toLowerCase().indexOf(this.state.search.toLowerCase()) !== -1
})
const dataArray = filteredCards.map(
(library) => {
return {title: library.title, content: library.desc}
}
)
return (
<View>
<Header searchBar rounded>
<Item>
<Icon name="ios-search" />
<Input placeholder="Search"
onChangeText={(value) => this.setState({search: value})}
/>
<Icon name="ios-people" />
</Item>
<Button transparent>
<Text>Search</Text>
</Button>
</Header>
<Accordion dataArray={dataArray} expanded={0}/>
</View>
);
}
}
I've tried different permutations of inline styling, but none of them seem to work. I'm very familiar with React, but I'm new to React Native.
Edit:
This is my current styling:
return (
<View>
<NewCard
createLibrary={this.createLibrary}
style={{
position: 'relative',
left: 20,
top: 20,
zIndex: 1
}}
/>
<Card style={{justifyContent: 'flex-end', position: 'absolute', zIndex: 0}} librarys={this.state.librarys}/>
</View>
);
}
}

Using a nested view with a "row" direction is useful here.
<view style={{flex:1}}>
<view style={{flexDirection:"row"}} >
<Searchabr/>
<Icon/>
...
</view>
</view>

If you want to position over the other item, you have to make the position: relative for the parent and set position: absolute for your icon. once you do this, you will now be able to place it using top, left, right, bottom and z-index properties accordingly.

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())
}
}

How to pass values from master screen to detail screen in React Native with wordpress a blog API backend?

Im in the process of developing react native application blog. I'm trying to fetch and display wordpress blog posts.
Im struck with the master detail linking between screen. I need a help in passing value from master to detail page.
All I need is when clicked on the list or card, it has to take to the detail page with particular Id.
I have two files MainPage.js and DetailsPage.js
MainPage.js
import React, { Component } from 'react';
import { Container, Header, Body, Title, Content, Card, CardItem, Text,
Button, Left, Icon } from 'native-base';
import {
StyleSheet,
Dimensions,
TextInput,
View,
ActivityIndicator,
Image,
} from 'react-native';
import Moment from 'moment';
import HTML from 'react-native-render-html';
import {createStackNavigator} from 'react-navigation';
export default class MainPage extends Component {
static navigationOptions = {
title: 'All Posts',
};
constructor(props) {
super(props);
this.state = {
isLoading: true,
posts: [],
};
}
_onDetailButtonPressed = () => {
this.props.navigation.navigate(
'Details');
};
componentDidMount() {
fetch('http://whatsnewsnet.com/wp-json/wp/v2/posts?_embed')
.then((response) => response.json())
.then((responseJson) => {
this.setState({
isLoading: false,
posts: responseJson,
})
})
.catch((error) => {
console.error(error);
});
}
render() {
const { navigate } = this.props.navigation;
if (this.state.isLoading == true) {
return(
<Container>
<View style={{ flex: 1, flexDirection: 'column', justifyContent: 'center', alignItems: 'center',}}>
<ActivityIndicator size="large" color="#1C97F7" />
</View>
</Container>
)
}
else{
Moment.locale('en');
return (
<Container>
<Content>
{this.state.posts.map((item, index) => (
<Card style={{flex: 0}} key = {item.id}>
<CardItem>
<Left>
<Body>
<Text onPress={this._onDetailButtonPressed} style = {{ fontSize: 24, fontWeight:'bold' }}>{item.title.rendered}</Text>
<Text note>Published on: {Moment(item.date).format('d MMM Y')}</Text>
</Body>
</Left>
</CardItem>
<CardItem>
<HTML html={item.excerpt.rendered} imagesMaxWidth={Dimensions.get('window').width} />
</CardItem>
<CardItem>
<Left>
<Button onPress={() => navigate('Details', { I do not know how to pass particular id from here to detail page})} transparent textStyle={{color: '#87838B'}}>
<Text>Author:</Text>
{item._embedded.author.filter( element => element.id ==item.author).map((subitem, index) => (
<Text key = {item.id}>{subitem.name}</Text>
))}
</Button>
</Left>
</CardItem>
</Card>
))}
</Content>
</Container>
)
}
}
}

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')
}

Why is my camera roll modal empty?

I am attempting to follow the React Native docs on accessing the Camera Roll. I have tried wrapping the camera roll images in a Modal Component. When I press the 'Open Camera Roll' button, the Modal comes up from the bottom with the 'close modal' button visible but none of the images from the camera roll.
When I didn't have it wrapped in a Modal, the images would appear but they would ruin the layout of all the components on my screen, which is why I am (unsuccessfully) trying to place it in a Modal.
Also, if you could give me some tips on how to make the images selectable and appear with 3 images/row it would be greatly appreciated.
import React from 'react';
import { CameraRoll, Image, Modal, ScrollView, Text, View } from 'react-native';
import { Button } from 'react-native-elements';
export default class AddEvent extends React.Component {
constructor(props){
super(props)
this.state = {
modalVisible: false,
photos: [],
}
}
getPhotos = () => {
CameraRoll.getPhotos({
first: 100,
})
.then(r => this.setState({ photos: r.edges }))
.catch((err) => {
alert('Error loading camera roll');
return;
});
}
openModal() {
this.getPhotos();
this.setState({modalVisible:true});
}
closeModal() {this.setState({modalVisible:false});}
static navigationOptions = ({ navigation }) => {
return {
headerTitle: (<Text>Camera Roll Test</Text>),
}
};
render(){
return (
<View>
<Modal
visible={this.state.modalVisible}
animationType={'slide'}
onRequestClose={() => this.closeModal()}>
<ScrollView>
{this.state.photos.map((p, i) => {
return (
<Image
key={i}
style={{width: 300, height: 100,}}
source={{ uri: p.node.image.uri }}/>
);
})}
</ScrollView>
<Button
onPress={() => this.closeModal()}
title="Close modal"/>
</Modal>
<Button
onPress={() => this.openModal()}/>
</View>
);
}
}
Got it, needed flex: 1 for <ScrollView> style and a contentContainerStyle. Doesn't look great but the photos show. Credit to u/Mingli91 on reddit.
import React from 'react';
import { CameraRoll, Image, Modal, ScrollView, StyleSheet, Text, View } from 'react-native';
import { Button } from 'react-native-elements';
const Dimensions = require('Dimensions');
const window = Dimensions.get('window');
const screenWidth = window.width;
const screenHeight = window.height;
export default class AddEvent extends React.Component {
constructor(props){
super(props)
this.state = {
modalVisible: false,
photos: [],
}
}
getPhotos = () => {
CameraRoll.getPhotos({
first: 100,
})
.then(r => this.setState({ photos: r.edges }))
.catch((err) => {
alert('Error loading camera roll');
return;
});
}
openModal() {
this.getPhotos();
this.setState({modalVisible:true});
}
closeModal() {this.setState({modalVisible:false});}
static navigationOptions = ({ navigation }) => {
return {
headerTitle: (<Text>Camera Roll Test</Text>),
}
};
render(){
return (
<View>
<Modal style={styles.modal}
visible={this.state.modalVisible}
animationType={'slide'}
onRequestClose={() => this.closeModal()}>
<ScrollView style={{flex: 1}}
contentContainerStyle={{ height: 100, width: 300 }}>
{this.state.photos.map((p, i) => {
return (
<Image
key={i}
style={{width: 300, height: 100,}}
source={{ uri: p.node.image.uri }}/>
);
})}
</ScrollView>
<Button
onPress={() => this.closeModal()}
title="Close modal"/>
</Modal>
<Button
onPress={() => this.openModal()}/>
</View>
);
}
}
const styles = StyleSheet.create({
modal: {
flex: 1,
alignItems: 'center',
width: screenWidth,
height: screenHeight,
}
});
Android 10
If you started noticing this on Android 10, try adding this to your AndroidManifest.xml:
<application
...
android:requestLegacyExternalStorage="true" />
Android is moving to "scoped storage". They started using this in Android 10, with the option to opt-out by adding android:requestLegacyExternalStorage="true" to your AndroidManifest.xml file.
However, starting in Android 11, this is a forced change and your value of android:requestLegacyExternalStorage will be ignored.
Read more here:
https://developer.android.com/training/data-storage/use-cases#opt-out-scoped-storage
Posting here because that was the issue with us and it surprisingly difficult to find out about.

Displaying props in a second target box

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>
);
}
}

Categories

Resources