I'm trying to load info from a json file using fetch and displaying data using a Listview React native component. Data from fetch is already load on my this.state.films, because if I try
<Text>{this.state.films[0].title}</Text>
I get the name of the film and that is ok. But when I try a Listview I only get "[]".
What am I doing wrong?? Actually I'm following React native doc and I am trinying to join two sections: "Networking" and "Using a list view". I took json from there.
Please Help,
Thanks!
That my code index.windows.js
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
Image,
TextInput,
ListView
} from 'react-native';
class AwesomeProject extends Component {
constructor(props) {
super(props)
this.state = { films: [] }
const ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
}
componentWillMount() {
fetch('http://facebook.github.io/react-native/movies.json')
.then((response) => {
return response.json()
})
.then((movies) => {
this.setState({ films: ds.cloneWithRows(movies.movie) })
})
}
render() {
return (
<View style={{paddingTop: 22}}>
<ListView
dataSource={this.state.films}
renderRow={(rowData) => <Text>{rowData.title}</Text>}
/>
</View>
);
}
}
AppRegistry.registerComponent('AwesomeProject', () => AwesomeProject);
React Native has a simpler solution, a FlatList, which works nicely, and wraps around the ListView. It can be used like this:
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
Image,
TextInput,
FlatList
} from 'react-native';
class AwesomeProject extends Component {
state = {
films: []
}
componentWillMount() {
fetch('http://facebook.github.io/react-native/movies.json')
.then( response => response.json())
.then((films) => {
this.setState({ films })
})
}
render() {
return (
<View style={{paddingTop: 22}}>
<FlatList
data={this.state.films}
renderItem={({item}) => <Text>{item.title}</Text>}
/>
</View>
);
}
}
AppRegistry.registerComponent('AwesomeProject', () => AwesomeProject);
Related
I was trying to display data from a fetch function to my render app in react native.
I was able to get the data from my fetch but i am not able to display it on the app..
this is my code:
import React from 'react';
import { StyleSheet, Text, View, Button } from 'react-native';
export default function App() {
const fetchDatos = async () => {
return fetch('http://localhost:8000/api/consulta').then(response => {
return response.json();
})
.then(responseJson => {
var Nombre = responseJson.Participante.InfoParticipante['#attributes'].Nombre;
});
}
return (
<View>
<Button
title='press me'
onPress={fetchDatos}
/>
<Text>{Nombre}</Text>
</View>
);
}
As you can see in the code above I get the data stored in the var ''Nombre'' and I am trying the display it in the app but it's telling me Uncaught ReferenceError: Nombre is not defined
Does anyone know how to fix this, I would appreciate it a lot!
This will work
import React,{useState} from 'react';
import { StyleSheet, Text, View, Button } from 'react-native';
export default function App() {
const [nombre,setNombre]=useState()
const fetchDatos = () => {
return fetch('http://localhost:8000/api/consulta').then(response => {
return response.json();
})
.then(responseJson => {
setNombre(responseJson.Participante.InfoParticipante['#attributes'].Nombre);
});
}
return (
<View>
<Button
title='press me'
onPress={fetchDatos}
/>
<Text>{nombre}</Text>
</View>
);
}
I'm fairly new to react native and redux and was trying to render the library title from a JSON file in a flat list using redux, but my FlatList component does not render anything on the screen.
here's my code :
LibraryList.js
import React, { Component } from "react";
import { FlatList } from "react-native";
import { connect } from "react-redux";
import ListItem from "./ListItem";
class LibraryList extends Component {
renderItem(library) {
return <ListItem library={library} />;
}
render() {
return (
<FlatList
data={this.props.libraries}
renderItem={this.renderItem}
keyExtractor={library => library.id}
/>
);
}
}
const mapStateToProps = state => {
return { libraries: state.libraries };
};
export default connect(mapStateToProps)(LibraryList);
ListItem.js
import React, { Component } from "react";
import { Text } from "react-native";
import { CardSection } from "./common";
class ListItem extends Component {
render() {
return (
<CardSection>
<Text>{this.props.library.title}</Text>
</CardSection>
);
}
}
export default ListItem;
App.js
import React from "react";
import { View } from "react-native";
import { Provider } from "react-redux";
import { createStore } from "redux";
import reducers from "./reducers";
import { Header } from "./components/common";
import LibraryList from "./components/LibraryList";
const App = () => {
return (
<Provider store={createStore(reducers)}>
<View>
<Header headerText="Tech Stack" />
<LibraryList />
</View>
</Provider>
);
};
export default App;
The JSON file is like
[
{
"id": '' ,
"title": '' ,
"description":''
},
{
"id":'' ,
"title":'' ,
"description":''
}
]
I read some solutions for this suggesting changing the renderItem function to something like this
renderItem = ({ library }) => <ListItem library={library} />
still does not work. Can someone help me with this problem?
Thanks.
You have to make your renderItem as an arrow function. Otherwise you have to bind your function inside constructor in order to access function as renderItem={this.renderItem}.
import React, { Component } from 'react';
import { FlatList } from 'react-native';
import { connect } from 'react-redux';
import ListItem from './ListItem';
class LibraryList extends Component {
renderItem = ({ item }) => {
return <ListItem library={item} />
}
render() {
return (
<FlatList
data={this.props.libraries}
renderItem={this.renderItem}
keyExtractor={library => library.id}
/>
);
}
}
const mapStateToProps = state => {
return { libraries: state.libraries };
};
export default connect(mapStateToProps)(LibraryList);
or you can call your renderItem as an arrow function inside render like below
renderItem={(item) => this.renderItem(item)}
but using an arrow function in render creates a new function each time the component renders, which may break optimizations based on strict identity comparison.
Hope this helps you. Feel free for doubts.
In your flatlist try thi s:
<FlatList
data={this.props.libraries}
renderItem={({item, index}) => {
this.renderItems(item); // change this name to renderItems so that it doesnt clash with flatlist default renderItem
}}
/>
Hope it helps. feel free for doubts
You have several approaches to your problem.
Firstly your renderItem should be binded, so either do this
renderItem = (library) => {
or this
renderItem={this.renderItem.bind(this)}
besides the binding problem, flatlist prop renderItem will return to your function an object with this structure
{ item, index }
so in reality your renderItem should be like this
renderItem({ item }){
return <ListItem library={item} />;
}
I am trying to print text content of login.php into the screen via "var result", but the fetch function won't alter value of "var result". How can I set value of result from output of the fetch function?
import React, { Component } from 'react';
import {
StyleSheet,
Text,
View,
StatusBar,
} from 'react-native';
import Logo from '../components/Logo';
import Form from '../components/Form';
import loginapi from '../apis/loginapi';
var result='noresult';
export default class Login extends Component<{}> {
render() {
login();
return (
<View style={styles.container}>
<Logo/>
<Form/>
<Text>
{result}
</Text>
<Text>
</Text></View>
);
}
}
function login() {
result = fetch('https://www.skateandstrike.com/loginsv/login.php').then((text) => {return text;});
}
const styles = StyleSheet.create({
container : {
backgroundColor:'#f05545',
flex: 1,
alignItems:'center',
justifyContent:'center',
}
});
function myFunction() {
this.setState({ showLoading: false });
}
This is not working too, using setState:
import React, { Component } from 'react';
import {
StyleSheet,
Text,
View,
StatusBar,
} from 'react-native';
import Logo from '../components/Logo';
import Form from '../components/Form';
import loginapi from '../apis/loginapi';
export default class Login extends Component<{}> {
constructor(){
super();
this.state = {
data:'NoData',
}
}
render() {
login();
return (
<View style={styles.container}>
<Logo/>
<Form/>
<Text>
{this.state.data}
</Text>
</View>
);
}
}
function login() {
fetch('https://www.skateandstrike.com/loginsv/login.php').then(data => this.setState(data));
}
const styles = StyleSheet.create({
container : {
backgroundColor:'#f05545',
flex: 1,
alignItems:'center',
justifyContent:'center',
}
});
function myFunction() {
this.setState({ showLoading: false });
}
Am I using setState in a wrong way? Thanks in advance for your help.
When using the fetch API, I'd recommend using a promise, and you parse it if you are setting the state.
React re-renders on state/props change.
sample code:
fetch(url)
.then(data => data.json()) // if needed
.then(data => this.setState(data))
remember to set state in the constructor.
We are trying to create a sample todo list application with React Native for a school project. Our issue is that we are not able to view the ListView items. All we are trying to do to at this point is to get an item to show up in a list. We have hardcoded the render to just show "Hello." Unfortunately, we are not seeing anything. We know that the component is being rendered because the console logs are showing output. We have been using this sample for guidance:
https://github.com/joemaddalone/react-native-todo
Here is our code:
ToDoListItem.js
import React, { Component } from 'react';
import {
Text,
View
} from 'react-native';
import styles from '../styles/styles';
export default class ToDoListItem extends Component {
render() {
console.log ("props: ", this.props)
var item = this.props.item;
return(
<View>
<View>
<Text style={{color: 'red'}}>TEST</Text>
<Text>{item.txt}</Text>
<Text>Hello</Text>
</View>
</View>
)
}
}
ToDoList.js
import React, { Component } from 'react';
import {
Text,
View,
ListView
} from 'react-native';
import ToDoListItem from './ToDoListItem';
export default class ToDoList extends Component {
constructor(props) {
super(props);
console.log("props: ", props.items)
};
componentWillMount(){
this.dataSource = new ListView.DataSource({
rowHasChanged: (r1, r2) => r1 !== r2
});
}
render() {
var dataSource = this.dataSource.cloneWithRows(this.props.items);
return(
<ListView
dataSource={dataSource}
renderRow={(rowData, sectionID, rowID) =>
<ToDoListItem item={rowData}/>
}
/>);
};
};
Try this:
import React, { Component } from 'react';
import {
Text,
View,
ListView,
AppRegistry
} from 'react-native';
class ToDoListItem extends Component {
render() {
var item = this.props.item;
return(
<View>
<View>
<Text style={{color: 'red'}}>TEST</Text>
<Text>{item.txt}</Text>
<Text>Hello</Text>
</View>
</View>
)
}
}
class ToDoList extends Component {
constructor(props) {
super(props);
};
componentWillMount(){
this.dataSource = new ListView.DataSource({
rowHasChanged: (r1, r2) => r1 !== r2
});
}
render() {
var dataSource = this.dataSource.cloneWithRows(['a','b','c']);
return(
<View>
<ListView
dataSource={dataSource}
renderRow={(rowData, sectionID, rowID) =>
{ return (<ToDoListItem item={rowData}/>) }
}
/>
</View>
);
};
};
AppRegistry.registerComponent('App', () => ToDoList)
Yay! Works!
I've merged two components. you can have it separated.
Better to render listview inside a view.
Make sure your datasource is properly set (this.props)
I need inside the file artistPage.js to refer to the TabNavigator in index.ios.js. In particular, I need to change the styles to hide the TabBar when the user is on the page artistPage.
How can I do that? Any ideas?
I tried to transfer styles in the props but there is the read-only mode(
index.ios.js
'use strict'
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
View,
Image,
Text,
NavigatorIOS,
TouchableHighlight,
NavigationBar,
} from 'react-native';
import config from './config';
import ImagesList from './app/imagesList';
import TabNavigator from 'react-native-tab-navigator';
import Badge from './node_modules/react-native-tab-navigator/Badge'
class MyApp extends Component {
constructor(props) {
super(props);
this.state = {
selectedTab: 'images',
showTabBar: true
};
}
render() {
let tabBarStyle = {};
let sceneStyle = {};
if (this.state.showTabBar) {
tabBarStyle = styles.tabBar;
sceneStyle.paddingBottom = 54;
} else {
tabBarStyle.height = 0;
tabBarStyle.overflow = 'hidden';
sceneStyle.paddingBottom = 0;
}
return (
<View style={styles.container}>
<TabNavigator
tabBarStyle={ tabBarStyle }
sceneStyle={sceneStyle}
>
<TabNavigator.Item
titleStyle={styles.title}
selectedTitleStyle={styles.title_select}
selected={this.state.selectedTab === 'images'}
title="TATTOOS"
renderIcon={() => <Image source={require('./images/tabbar/tattoos_icon.png')} />}
renderSelectedIcon={() => <Image source={require('./images/tabbar/tattoos_icon_selected.png')} />}
onPress={() => this.setState({ selectedTab: 'images' })}>
<NavigatorIOS
style={styles.container}
initialRoute={{
title: 'MyApp',
component: ImagesList,
passProps: { showTabBar: true},
}}
navigationBarHidden={true}/>
</TabNavigator.Item>
</TabNavigator>
</View>
);
}
}
AppRegistry.registerComponent('MyApp', () => MyApp);
imageList.js
'use strict'
import React, { Component } from 'react';
import {
StyleSheet,
ListView,
View,
Text,
Image,
Dimensions,
ActivityIndicator,
TouchableHighlight,
RefreshControl
} from 'react-native';
import ArtistPage from './imageCard';
class ImagesList extends Component {
constructor(props) {
super(props);
this.state = {
};
}
_artistPage() {
this.props.navigator.push({
component: ArtistPage
});
}
render() {
return (
<View style={styles.container}>
<TouchableHighlight
onPress={this._artistPage()}
>
<Text>Got to Next Page</Text>
</TouchableHighlight>
</View>
);
}
}
}
module.exports = ImagesList;
artistPage.js
'use strict'
import React, { Component } from 'react';
import {
StyleSheet,
Text,
ListView,
View,
TouchableHighlight,
Image,
} from 'react-native';
class ArtistPage extends Component {
constructor(props) {
super(props);
this.state = {
};
}
_backTo() {
this.props.navigator.pop();
}
render() {
return (
<View>
<TouchableHighlight style={{marginTop: 100, marginLeft: 50}} onPress={() => this._backTo()} >
<Text>Back {this.props.showTabBar.toString()}</Text>
</TouchableHighlight>
</View>
);
}
}
module.exports = ArtistPage;
Here is how to hide TabNavigator: https://github.com/exponentjs/react-native-tab-navigator
let tabBarHeight = 0;
<TabNavigator
tabBarStyle={{ height: tabBarHeight, overflow: 'hidden' }}
sceneStyle={{ paddingBottom: tabBarHeight }}
/>
But I don't understand how to access it from artistPage.js
Thank you!
Data flow in React is one way. What it means in practice is that, to change something that a certain component receives via props, it will need to call back into the parent component, via a function from props.
The React website has a nice intro to the concept.
In your particular case, you could have a tabBarVisible state in MyApp, and inside render, compute the style to apply to the tab bar.
MyApp also can have a method to change this state:
hideTabBar() {
this.setState({ tabBarVisible: true });
}
Now, in order to let ArtistPage toggle that, you can pass the hideTabBar function from MyApp to ArtistPage as a prop, and call it in ArtistPage in a lifecycle hook, like componentDidMount.