I am new to react native and while going through a tutorial , I got stuck with scrolling of FlatList. On the tutorial with the same code I can see the list is scrolling. I am using Android emulator.
class LibraryList extends Component {
renderItem = ({ item }) => (
<ListItem library={item} />
);
render() {
console.log(this.props.libraries);
return (
<FlatList
data={this.props.libraries}
renderItem={this.renderItem}
keyExtractor={library => library.id.toString()}
/>
);
}
}
const mapStateToProps = state => {
return { libraries: state.libraries };
};
export default connect(mapStateToProps)(LibraryList);
Try by wrapping your FlatList with the empty View having flex is 1.
So your render method code will be like below code:
render() {
console.log(this.props.libraries);
return (
<View style={{flex:1}}>
<FlatList
data={this.props.libraries}
renderItem={this.renderItem}
keyExtractor={library => library.id.toString()}
/>
</View>
);
}
Hope this will help you.
Try this code block (example , change this self code)
renderFlatList() {
return (
<FlatList
data={this.props.database}
ListHeaderComponent={() => this.renderAddFeedScool()}
renderItem={({ item }) => this.renderItem(item)}
/>
);
}
render() {
return (
<View style={_styles.container}>
{this.props.database.length > 0 ? (
this.renderFlatList()
) : (
<Text>Loading</Text>
)}
</View>
);
}
Styles..
container: {
flex: 1,
},
Full code : https://github.com/VB10/Nativer/blob/master/src/view/tab/school/index.tsx
And look at https://facebook.github.io/react-native/docs/flatlist
and :) final solution use native-base list component i think exactly solution https://docs.nativebase.io/Components.html#list-def-headref
Good work.
Related
I'm making a list view were I will view a list of some data from my database. But after running the program all I got is white background screen. Does anyone knows the solution?
screen shot
Here is my code
export default class Pasta extends Component {
constructor() {
super()
this.state = {
dataSource: []
}
}
renderItem = ({ item }) => {
return (
<View style = {{flex: 1, flexDirection: 'row'}}>
<View style = {{flex: 1, justifyContent: 'center'}}>
<Text>
{item.menu_desc}
</Text>
<Text>
{item.menu_price}
</Text>
</View>
</View>
)
}
componentDidMount() {
const url = 'http://192.***.***.***:9090/menu'
fetch(url)
.then((response) => response.json())
.then((responseJson) => {
this.setState({
dataSource: responseJson.menu
})
})
}
render() {
return (
<View style = { styles.container }>
<FlatList
data = { this.state.dataSource }
renderItem = {this.renderItem}
/>
</View>
);
}
}
Add extraData prop to your FlatList to cause a re-render
keyExtractor = (item, index) => item.id; // note: id is the unique key for each item
render() {
return (
<FlatList
data = {this.state.dataSource}
renderItem = {this.renderItem}
extraData={this.state}
keyExtractor={this.keyExtractor}
/>
);
}
Also log and verify your data is present. I suggest referring to FlatList docs for more props like keyExtractor etc.
I am new to React Native so excuse the question if this is simple. I am trying to toggle icons in a ListView. How should I go about this? Your help is much appreciated.
Here's a piece of code i'm working with.
this.state = {
logo: 'star-o',
check: false
};
saveFavourite = (data) => {
this.state.check === false ? this.setState({logo:'star', check:true}) : this.setState({logo:'star-o', check:false})
}
<TouchableOpacity onPress={() => this.saveFavourite(data)}>
<Icon name={this.state.logo} size={30} />
</TouchableOpacity>
it din't change the icon.
First I can guess by your code that you are addressing this in the component holding the list view. This is wrong because you cant define a state to every "loveable" component, mainly because you cannot know how many are they beforehand. Instead, you should try to make this component dummy and receive if it is loved or not by props.
Then you should put a callback inside your component to execute code from your parent Component. Something like this:
class MyListComponent extends React.Component {
state = {
items: [
{ text: 'Some text', loved: false },
{ text: 'Some text2', loved: true },
],
}
toggleLoved() => {
// your logic here
}
render() {
return(
<FlatList
data={this.state.items}
renderItem={(item) => {
<MyLoveableComponent
loved={item.item.loved}
onLoved={ () => this.toggleLoved() }
}/>
);
}
}
const MyLoveableComponent = ({ loved, onLoved, logo }) => {
return(
<TouchableOpacity
onPress={() => {
setFavourite();
onLoved();
}>
<Icon name={logo} size={30} />
</TouchableOpacity>);
}
}
Check the component-container design pattern and remind that components should be as dummy as possible.
I am trying to use react-native-sidemenu https://github.com/react-native-community/react-native-side-menu
My code looks like this.
There is no error and even output is overlapping to each other
var list = [{name: "komaldeep", subtitle: "dssdfds", avatar_url:"sadasdsa" }];
export default class First extends Component {
constructor(props) {
super(props);
this.state = {
isOpen: false,
};
this.toggleSideMenu = this.toggleSideMenu.bind(this);
}
toggleSideMenu () {
this.setState({
isOpen: !this.state.isOpen
})
}
render() {
//menu list `enter code here`
const MenuComponent = (
<View style={{flex: 1, backgroundColor: '#ededed', paddingTop: 200}}>
<List containerStyle={{marginBottom: 20}}>
{
list.map((l, i) => (
<ListItem
roundAvatar
onPress={() => console.log('Pressed')}
avatar={l.avatar_url}
key={i}
title={l.name}
subtitle={l.subtitle}
/>
))
}
</List>
</View>
)
return (
<SideMenu
isOpen={this.state.isOpen}
menu={MenuComponent} >
//Menu Component just contain some random text
<Menu toggleSideMenu={this.toggleSideMenu.bind(this)}/>
</SideMenu>
);
}
}
Can you just guide me.. what i am doing wrong..
OutPut looks like this
enter image description here
The reason that the items in your menu shows up on the right of the screen, seemingly outside of the menu, is that your MenuComponent takes up the entire screen. Set the prop openMenuOffset={number} to SideMenu and use the same number to set width: number in the style of your MenuComponent.
I know how to add and remove a single component by changing the state. But this way wont work if you have multiple components to remove. For instance lets say I have 3 Views. How can I remove them when I click on them.
Example code:
class Example extends Component {
render(){
return (
<View>
<View>
<TouchAbleOpacity onPress={() => this.removeView()}>
<Text>Remove View 1</Text>
</TouchAbleOpacity>
</View>
<View>
<TouchAbleOpacity onPress={() => this.removeView()}>
<Text>Remove View 2</Text>
</TouchAbleOpacity>
</View>
<View>
<TouchAbleOpacity onPress={() => this.removeView()}>
<Text>Remove View 3</Text>
</TouchAbleOpacity>
</View>
</View>
)
}
removeView(){
}
}
Another example will be when I have a ListView with buttons inside. These are buttons to invite a user. When I click on the button I want to hide the button for that specific row in the ListView.
Any suggestions?
Thanks to Giorgos I found a solution for my own question. I created a separate component with a hide function inside the component. Now I can just add this component anywhere in a view or in a listView and when I click on it it will hide. Remember this only hides the component and does not unmount it.
This is just an example so I created a button component.
My Button Component:
class ButtonComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
hide:false
}
}
render() {
return (
<View style={styles.container}>
{this.renderButtonComponent()}
</View>
);
}
renderButtonComponent(){
if(!this.state.hide){
return (
<TouchableOpacity onPress={this.hide.bind(this)}>
<Text>Button</Text>
</TouchableOpacity>
);
}
}
hide(){
this.setState({
hide:true
});
}
}
In my View I just render my Component:
render() {
return (
<View style={styles.container}>
<ButtonComponent/>
<ButtonComponent/>
<ButtonComponent/>
</View>
);
}
You have to use your component's state. Whenever you call setState the component's render() function is triggered again. There based on what the current state is, you can decide what to show and what not. For example:
class Example extends Component {
constructor(props){
// initialize state
this.state = {
isView1Visible: true,
isView2Visible: true,
isView2Visible: true
}
}
render(){
return (
<View>
{ this.renderView1() }
{ this.renderView2() }
{ this.renderView3() }
</View>
)
}
renderView1(){
if(this.state.isView1Visible){
return (
<View>
<TouchAbleOpacity onPress={() => this.setState( {isView1Visible: false} )}>
<Text>Remove View 1</Text>
</TouchAbleOpacity>
</View>
)
}
renderView2(){
if(this.state.isView2Visible){
return (
...
)
}
renderView3(){
if(this.state.isView3Visible){
return (
...
)
}
}
In the above example, you render your view based on the current state. When the button is clicked, you update the state by calling setState() which, like I mentioned before, will trigger another call to render().
With the ListView the approach is the same but the implementation slightly different. What you need to do there is to save your list of items in the state of your component and whenever you want to add/remove an item, you update the list accordingly and then update the state using setState. For example, something similar to this:
constructor(props) {
super(props);
var list = [ ... ]
const ds = new ListView.DataSource({ rowHasChanged: (r1, r2) => r1 !== r2 });
this.state = {
dataSource: ds,
items: ds.cloneWithRows(list)
};
}
render() {
return (
<View>
<ListView
dataSource={this.state.items}
renderRow={(rowData) => this.renderRow(rowData) /> } />
</View>
)
}
renderRow(rowData) {
<View>
<TouchAbleOpacity onPress={() => this.updateList()}>
<Text>Remove View 1</Text>
</TouchAbleOpacity>
</View>
}
updateList() {
// do some changes to your list and update the state.
var newItems = ...
this.setState({
items: newItems
})
}
Hope this helps.
Working with a ListView in React-Native, I have seen that is not the same, moving props to the list item,
Pass functions as props only with the reference, and invoke the parameters in the child component, or
Pass functions as props with parameters defined, and invoke the function with no parameters in the child
None of the solutions works.
The function invoked are Actions creators of Redux, and dispatched. Is this a issue of Redux or React-Native (maybe ReactJS)
This is a snippet, market as //ERROR the code lines that does'nt work followed by the good ones
class App extends Component {
// On props
// data: an Array
// doThis: an action creator of Redux
// doThat: idem
constructor(){
super();
this.ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
}
render () {
const dataSource = this.ds.cloneWithRows(this.props.data);
return (
<View>
<ListView style={{flex:1}}
dataSource={dataSource}
renderRow={(rowData, sectionID, rowID) =>
<Item rowData={rowData}
//ERROR
//onPress={this.props.doThis}
//onLongPress={this..props.doThat}
//RIGHT NO ERROR TOO
onPress={() => this.props.doThis(rowData)}
onLongPress={() => this.props.doThat(rowData)}
/>
}
/>
</View>
)
}
}
class Item extends Component {
render() {
return (
<View>
<TouchableHighlight
//ERROR
//onPress={() => { this.props.onPress( this.props.rowData ) }}
//onLongPress={() => { this.props.onLongPress( this.props.rowData ) }}
//WRONG TOO
onPress={this.props.onPress}
onLongPress={this.props.onLongPress}
>
<Text>
{rowData}
</Text>
</TouchableHighlight>
</View>
);
}
}
There is a repo with this problem here https://github.com/srlopez/test
Thanks in advance
If your high-level callbacks accept a parameter, you need to make sure your anonymous functions accept a parameter as well (Note: creating anonymous functions using the arrow syntax automatically binds our function to the value of this in the current context). I think you witnessed a combination of issues where either your callbacks were bound to the incorrect context (the window) or you weren't accepting the passed arguments:
class App extends Component {
// On props
// data: an Array
// doThis: an action creator of Redux
// doThat: idem
constructor(){
super();
this.ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
}
render () {
const dataSource = this.ds.cloneWithRows(this.props.data);
return (
<View>
<ListView style={{flex:1}}
dataSource={dataSource}
renderRow={(rowData, sectionID, rowID) =>
<Item rowData={rowData}
onPress={(data) => this.props.doThis(data)}
onLongPress={(data) => this.props.doThat(data)} />
}/>
</View>
)
}
}
class Item extends Component {
render() {
return (
<View>
<TouchableHighlight
onPress={() => this.props.onPress(this.rowData)}
onLongPress={() => this.props.onLongPress(this.rowData)}>
<Text>
{rowData}
</Text>
</TouchableHighlight>
</View>
);
}
}
It's probably be a problem with your this not being set right in your closure.
Try binding it this way:
class Item extends Component {
render() {
return (
<View>
<TouchableHighlight
onPress={this.props.onPress.bind(this, this.props.rowData)}
onLongPress={this.props.onLongPress.bind(this, this.props.rowData)}
>
<Text>
{rowData}
</Text>
</TouchableHighlight>
</View>
);
}
}