React-native I loop through it, but nothing comes out of the children - react-native

I tried to show images and people's names using loops.
import { StyleSheet, Text, View, SafeAreaView, ScrollView } from 'react-native'
import React from 'react'
import Header from './home/Header'
import Stories from './home/Stories'
import Posts from './home/Posts'
import { POSTS } from '../data/posts'
const HomeScreen = () => {
return (
<SafeAreaView style={styles.container}>
<Header></Header>
<ScrollView>
<Stories></Stories>
{POSTS.map((post, index) => (
<Posts post={post} key={index}/>
))}
</ScrollView>
</SafeAreaView>
)
}
export default HomeScreen
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: 'black'
},
});
This is the one that has a problem.
import { Image, StyleSheet, Text, View } from 'react-native'
import {Divider} from 'react-native-elements'
import React from 'react'
const Posts = ({post, index}) => {
return (
<View stlye={styles.conatiner}>
<Divider width={1} orientation='vertical'></Divider>
<PostHeader post={post} key={index}/> <--- this part not show up
</View>
)
};
const PostHeader = ({post, index}) => {
<View style={{flexDirection: 'row', justifyContent: 'space-between', margin: 5, alignContent: 'center'}} key={index}>
<View>
<Image source={{ uri: post.profile_pictrue}} style={styles.story}/>
<Text style={{color: 'white'}}>{post.user.user}</Text>
</View>
</View>
};
const styles = StyleSheet.create({
conatiner: {
marginBottom: 30
},
story: {
width: 35,
height: 35,
borderRadius: 50,
marginBottom: 10,
borderWidth: 2,
borderColor: 'orange'
},
});
export default Posts
But the divider is working. And, there is no error log.
I don't understand what have I done wrong.

you need to wrap with return
const PostHeader = ({post, index}) => {
return( <View style={{flexDirection: 'row', justifyContent: 'space-between', margin: 5, alignContent: 'center'}} key={index}>
<View>
<Image source={{ uri: post.profile_pictrue}} style={styles.story}/>
<Text style={{color: 'white'}}>{post.user.user}</Text>
</View>
</View>)
};
hope it's working fine

Related

React native button onpress show 2 new buttons and make other stuff unclickable

I want after press on the FloatingButton, to show 2 more buttons.
While I have these 2 buttons shown, I want to make the rest of this page to be uncklickable,
that the user has to press one of these to go on navigating.
This is my code:
import React from 'react';
import { StyleSheet, Text, View, ScrollView } from 'react-native';
import FloatingButton from '../components/FloatingButton';
const DuellScreen = () => {
return (
<View style={{ flex: 1 }}>
<ScrollView style={styles.container2}>
<Text style={{ flex: 1 }}>body</Text>
</ScrollView>
<View style={styles.container}>
<FloatingButton/>
</View>
</View>
)
}
const styles = StyleSheet.create({
container: {
padding: 16,
flex: 1,
backgroundColor: '#fff',
justifyContent: 'flex-end',
alignItems: 'center'
},
container2: {
padding: 16,
flex: 5,
backgroundColor: '#fff',
},
});
export default DuellScreen
How can I do this, especially the 2 button visible after buttonpress + make the other things unclickable?
how about this:
import React, { useState } from 'react';
import { StyleSheet, Text, View, ScrollView } from 'react-native';
import FloatingButton from '../components/FloatingButton';
const DuellScreen = (props) => {
const [active, setActive] = useState(true);
return (
<View style={{ flex: 1 }}>
<ScrollView style={styles.container2}>
<Text style={{ flex: 1 }}>body</Text>
</ScrollView>
<View style={styles.container}>
<FloatingButton onPress={active ? () => setActive(false) : () => {} } />
{!active ?
<View>
<FloatingButton onPress={() => props.navigation.navigate('OtherScreen')} />
<FloatingButton onPress={() => props.navigation.navigate('AnotherScreen')} />
</View>
: null}
</View>
</View>
)
}

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

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

React Native component loose arrangement when a new component is added

I have the following view in a React Native app:
And this is the code for it:
index.js
import React, {useContext} from 'react';
import {View, StyleSheet} from 'react-native';
import {Headline, Button, IconButton} from 'react-native-paper';
import ShoppingCartEntry from './ShoppingCartEntry';
import ShoppingCartContext from '../../context/shoppingCart/shoppingCartContext';
const ShoppingCartList = () => {
const {shoppingCart} = useContext(ShoppingCartContext);
const TotalPriceDisplay = () => {
let totalPrice = 0;
shoppingCart.map((entry) => {
totalPrice = totalPrice + (entry.product.price * entry.amount);
})
return (
<Headline>Total: {totalPrice}</Headline>
)
}
return (
<View style={styles.cartContainer}>
<View style={styles.icon}>
<IconButton icon='cart' color='black' size={40}/>
</View>
{shoppingCart.map((entry) => {
return (
<ShoppingCartEntry entry={entry} />
)
})}
<View style={styles.totalPrice}>
<TotalPriceDisplay />
<Button mode='contained'>
Comprar
</Button>
</View>
</View>
)
}
styles = StyleSheet.create({
cartContainer: {
flexDirection: 'column',
},
totalPrice: {
alignItems: 'center'
},
icon: {
alignItems: 'center'
}
})
export default ShoppingCartList;
ShoppingCartEntry.js
import React, {useContext} from 'react';
import {View, StyleSheet} from 'react-native';
import {Headline, IconButton, Text} from 'react-native-paper';
import ShoppingCartContext from '../../context/shoppingCart/shoppingCartContext';
const ShoppingCartEntry = ({entry}) => {
const {shoppingCartAppendProduct, shoppingCartUpdateProduct, shoppingCartRemoveProduct} = useContext(ShoppingCartContext);
const removeProduct = () => {
shoppingCartRemoveProduct(entry.product.id);
}
const Counter = () => {
return (
<View style={styles.counterContainer}>
<View style={styles.counter}>
<IconButton icon='plus' color='black' onPress={removeProduct} />
</View>
<View>
<Headline color='blue'>{entry.amount}</Headline>
</View>
<View style={styles.counter}>
<IconButton icon='minus' color='black' onPress={removeProduct} />
</View>
</View>
)
}
return (
<View style={styles.entryContainer}>
<View style={styles.button}>
<IconButton icon='delete' color='red' onPress={removeProduct} />
</View>
<View style={styles.name}>
<Headline>{entry.product.name}</Headline>
<Text>{entry.product.price}</Text>
</View>
<View style={styles.amount}>
<Counter />
<Text style={{textAlign: 'right'}}>{entry.product.price * entry.amount}</Text>
</View>
</View>
)
}
styles = StyleSheet.create({
entryContainer: {
flexDirection: 'row',
paddingBottom: 20,
paddingLeft: 20
},
name: {
flex: 0.5
},
amount: {
flex: 0.3
},
button: {
alignItems: 'flex-end',
flex: 0.1
},
counterContainer: {
flexDirection: 'row'
},
counter: {
alignItems: 'flex-end',
justifyContent: 'center',
flexDirection: 'row'
}
})
export default ShoppingCartEntry;
The problem is that when an element is removed from shoppingCart and the whole view is re rendered, it looses all its formatting:
I discovered that all I have to do is to change the StyleSheet.flexDirection for the container from row to column and, then, back to row again, and the view gets arranged again, but now with the new data.
I don't know if this is a development stage issue that I shouldn't care about for production, or if there is something I can do to avoid it.
You should add flex:1 to your base container styles for both your list and your item.
...
entryContainer: {
flex:1,
flexDirection: 'row',
paddingBottom: 20,
paddingLeft: 20
},
...
cartContainer: {
flex:1,
flexDirection: 'column',
},

A problem with a trivial react native code with hooks

Update:
Problem 2. is solved (thanks to #NikolayNovikov reply) by replacing "setResources({ resources: response.data })" with
"setResources(response.data)".
Problem 1. I cannot reproduce it...
Description of the problem:
The following trivial example is fetching data from jsonplaceholder.typicode.com, and, since there are 100 'posts' and 200 'todos', it is supposed to display 100 and 200 when you click on these buttons.
For some reason that I cannot find (embarrassing, I know...), there are two problems:
When I click on the 'posts' button, useEffect is called twice (once with 'todos' and once with 'posts', and when I click on the 'todos' button it is not called at all.
resource.length is not rendered
Any idea what is wrong?
App.js:
import React, { useState } from 'react';
import { View, TouchableOpacity, Text, StyleSheet } from 'react-native';
import { ResourceList } from './components/ResourceList';
console.warn('In App.js: Disabling yellowbox warning in genymotion');
console.disableYellowBox = true;
export const App = () => {
const [resource, setResource] = useState('todos');
return (
<View style={{ flex: 1, alignItems: 'center', marginTop: 100 }}>
<Text style={{ fontSize: 20, fontWeight: '500' }}>
The Application has been loaded!
</Text>
<View style={{ flexDirection: 'row', marginTop: 100,
alignItems: 'center', justifyContent: 'center' }}>
<TouchableOpacity onPress={() => setResource('posts')}>
<View style={styles.button}>
<Text style={styles.buttonText}>
Posts
</Text>
</View>
</TouchableOpacity>
<View style={{ width: 20 }} />
<TouchableOpacity onPress={() => setResource('todos')}>
<View style={styles.button}>
<Text style={styles.buttonText}>
Todos
</Text>
</View>
</TouchableOpacity>
</View>
<ResourceList resource={resource} />
</View>
);
}
const styles = StyleSheet.create({
buttonText: {
color: 'black',
fontSize: 20
},
button: {
backgroundColor: '#a8a',
justifyContent: 'center',
alignItems: 'center',
paddingVertical: 5,
paddingHorizontal: 10,
borderRadius: 2
}
});
ResourceList.js:
import React, { useState, useEffect } from 'react';
import { View, Text } from 'react-native';
import axios from 'axios';
// export const ResourceList = (props) => {
export const ResourceList = ({ resource }) => { // restructured props
const [resources, setResources ] = useState([]);
const fetchResource = async(resource) => {
console.log('+++ ResourceList/fetchResource calling axios. path:',
`https://jsonplaceholder.typicode.com/${resource}`);
const response = await axios.get(`https://jsonplaceholder.typicode.com/${resource}`);
console.log(response);
setResources({ resources: response.data })
}
useEffect(() => {
console.log('--- ResourceList/useEffect. resource: ', resource);
fetchResource(resource);
}, [resource]);
return (
<View style={{ flex: 1, alignItems: 'center', marginTop: 100 }}>
<Text style={{ fontSize: 20, fontWeight: '500' }}>
{resources.length}
</Text>
</View>
);
}
In you ResourceList.js component setResources should be different, please try this:
setResources(response.data)

How to show two views per rows in scollview in React native

How to show two views per rows in scollview in React native?
It is difficult to change the large framework since I made a view by pulling the json with module.
I would like to show views in the scrollview in the form shown below.
enter image description here <-- image link
I’d be glad if you could help me.
** If it have no idea in current method, you can give me a new idea.
this is code (const styles skipped)
import React, { Component } from 'react';
import { StyleSheet, View, Text, Image, StatusBar, FlatList, ScrollView, TouchableOpacity, Button, Dimensions } from 'react-native';
import logoImg from '../../images/logo.png';
import SearchInput, { createFilter } from 'react-native-search-filter';
import Icon from 'react-native-vector-icons/FontAwesome';
import Icon2 from 'react-native-vector-icons/Feather';
import promotion_list from '../../data/market_list.js';
const KEYS_TO_FILTERS = ['name', 'subject'];
const myIcon = (<Icon name="times" size={25} color='#949494' />)
export default class Market extends React.Component {
constructor(props) {
super(props);
this.state = {
searchTerm: ''
}
}
searchUpdated(term) {
this.setState({ searchTerm: term })
}
render() {
const filteredlists = promotion_list.filter(createFilter(this.state.searchTerm, KEYS_TO_FILTERS))
return (
<View style={styles.SearchList}>
<View style={{ flexDirection: 'row', margin: 10, padding: 10, height: 40, borderRadius: 100, backgroundColor: '#f5f5f5' }}>
<Icon name="search" size={20} color='#949494' style={{ flex: 0, marginRight: 10 }} />
<SearchInput
clearIcon={myIcon}
clearIconViewStyles={{ position: 'absolute', right: 6 }}
onChangeText={(term) => { this.searchUpdated(term) }}
placeholder="Search"
inputViewStyles={{ flex: 1 }}
/>
</View>
<View style={{justifyContent: 'center', alignItems: 'center'}}>
<Image style={{width:390, height:180}} source={require("../../images/market/topview.png")} />
</View>
<View>
<Text style={{marginLeft:15, marginTop:10, marginBottom:10, fontWeight:'bold', fontSize:20, color: '#494a51'}}>Your Partners</Text>
</View>
<ScrollView style={styles.ScrollView}>
{filteredlists.map(plist => {
function getImage(img_name) {
switch (img_name) {
case "1.png": return require("../../images/par_logo/1.png");
case "2.png": return require("../../images/par_logo/2.png");
case "3.png": return require("../../images/par_logo/3.png");
case "4.png": return require("../../images/par_logo/4.png");
case "5.png": return require("../../images/par_logo/5.png");
case "6.png": return require("../../images/par_logo/6.png");
case "7.png": return require("../../images/par_logo/7.png");
case "p1.png": return require("../../images/promotion_feed/1.png");
case "p2.png": return require("../../images/promotion_feed/2.png");
case "p3.png": return require("../../images/promotion_feed/3.png");
case "p4.png": return require("../../images/promotion_feed/4.png");
case "p5.png": return require("../../images/promotion_feed/5.png");
}
}
return (
<TouchableOpacity activeOpacity={1} key={plist.id} style={styles.ListItem}>
<View style={{ paddingRight: 10, paddingLeft: 10, height: 50, flexDirection: 'row', alignItems: 'center' }}>
<Image style={{ marginRight: 10, width: 30, height: 30, resizeMode: Image.resizeMode.contain }} source={getImage(plist.src1)} />
<Text style={{ fontWeight: 'bold' }}>{plist.name}</Text>
</View>
<View style={{margin:0}}>
<TouchableOpacity onPress={() => { alert("you clicked me") }}>
<Image style={{}} source={getImage(plist.src2)} />
</TouchableOpacity>
</View>
</TouchableOpacity>
)
})}
</ScrollView>
</View>
)
}
}
One possible solution is to use a FlatList which is inherited from ScrollView and use the numColumns prop. FlatList