Where should i use setState? - reactjs

In my react native project, i am trying to make a basic currency converter. In home.js you can see a component which name is InputWithButton. This component has a button which has a buttonText and it's value baseCurrency. When i click this button, CurrencyList screen is open. In CurrencyList there is a flatlist which has currency values. I can selected a value in flatlist in CurrencyList and i can send this value to the home screen with this.props.navigation.navigate('Home',{selected:item}) but when i back to home screen with back button i dont know how to change buttonText's value in InputWithButton's component. i dont know where should i use setState?
Home.js
import React, {Component} from 'react';
import {View, Text, Button} from 'react-native';
import {InputWithButton} from '../components/TextInput';
//const TEMP_BASE_CURRENCY = 'USD';
//const TEMP_CONVERT_CURRENCY = 'GBP';
class Home extends Component {
constructor(props) {
super(props);
this.state = {
baseCurrency: 'TRY', //Başlangıç olarak sayfa açıldığında gelecek olan değerler
convertCurrency: 'USD',
amount: null,
result: '',
date: '',
};
//const selected = this.props.route.params;
}
calculate = () => {
const amount = this.state.amount;
let url =
'https://api.exchangeratesapi.io/latest?base=' + this.state.baseCurrency;
fetch(url, {
method: 'GET',
})
.then((res) => res.json())
.then((data) => {
const date = data.date;
const result = (
data.rates[this.state.convertCurrency] * amount
).toFixed(2);
this.setState({
result,
date,
});
})
.catch((error) => {
console.log(error);
});
};
handleChangeText = (text) => {
//Yazıda değişim algılandığında api işlemleri başlasın
this.setState(
{
amount: text,
},
this.calculate,
);
};
handlePressBaseCurrency = () => {
//flatlist sayfası açılsın
const {navigation} = this.props;
navigation.navigate('CurrencyList');
};
handlePressConvertCurrency = () => {
//flatlist sayfası açılsın
};
render() {
const {baseCurrency, convertCurrency, result} = this.state;
return (
<View>
<InputWithButton
buttonText={baseCurrency}
onPress={this.handlePressBaseCurrency}
keyboardType="numeric"
onChangeText={(text) => this.handleChangeText(text)}
/>
<InputWithButton
editable={false}
buttonText={convertCurrency}
onPress={this.handlePressConvertCurrency}
value={result}
/>
<Button
title="Ceviri"
onPress={() => this.props.navigation.navigate('Ceviri')}
/>
</View>
);
}
}
export default Home;
CurrencyList.js
import React, {Component} from 'react';
import {View, FlatList, Text} from 'react-native';
import currencies from '../data/currencies';
import {ListItem, Separator} from '../components/List';
const temp_base_currency = 'CAD';
class CurrencyList extends Component {
constructor(props) {
super(props);
this.state = {
selectedItem: '',
};
}
handlePress = (item) => {
this.setState({
selectedItem: item, //__
});
// const {navigate} = this.props.navigation;
// navigate('Home', {clickedItem: this.state.selectedItem});
//Tıklandığında beklesin
this.props.navigation.navigate('Home', {selected: item}); //__
};
render() {
return (
<View>
<FlatList
renderItem={({item}) => (
<ListItem
onPress={() => this.handlePress(item)}
text={item}
selected={item === this.state.selectedItem} //__
/>
)}
data={currencies}
keyExtractor={(item) => item}
ItemSeparatorComponent={Separator}
/>
</View>
);
}
}
export default CurrencyList;

Related

How do you create dynamic/update-able routes with react-native-tab-view?

I have the following component. It works great to create the initial set of tabs.
import * as React from 'react';
import { TabBar, TabView } from 'react-native-tab-view';
import { CollectionList } from './components';
const renderTabBar = (props) => <TabBar {...props} scrollEnabled />;
const RarityTabs = ({ collectionId, rarities }) => {
const rarityRoutes = rarities.map((rarity) => ({
key: rarity.variant,
title: rarity.quality,
rarity,
}));
const [index, setIndex] = React.useState(0);
const [routes, setRoutes] = React.useState(rarityRoutes);
return (
<TabView
lazy
navigationState={{ index, routes }}
renderScene={({ route }) => (
<CollectionList collectionId={collectionId} selectedRarity={route.rarity} />
)}
renderTabBar={renderTabBar}
onIndexChange={setIndex}
/>
);
};
export default RarityTabs;
However, rarities can change and I'd like to make the tab route creation respond accordingly.
When I try useEffect to to fire setRoutes it locks up the app.
How can do you create a way for routes to be dynamic? Thanks!
Also posted on GitHub
import * as React from 'react';
import {View, StyleSheet} from 'react-native';
import {TabView, TabBar, SceneMap} from 'react-native-tab-view';
import {connect} from 'react-redux';
import Categories from './Categories';
export default class CategoriesScrollable extends React.Component {
constructor(props) {
super(props);
const {monthList, selected} = props;
this.state = {
index: selected,
screens: {},
routes: monthList,
};
}
componentDidMount() {
let screens = {};
for (let i = 0; i < this.state.routes.length; i++) {
screens[[`${this.state.routes[i].key}`]] = Categories;
}
this.setScreen(screens);
}
setScreen = (param) => {
this.setState({screens: SceneMap(param)});
};
handleIndexChange = (index) =>
this.setState({
index,
});
renderTabBar = (props) => (
<TabBar {...props} scrollEnabled />
);
render() {
return (
<View style={{flex: 1, backgroundColor: Color.white}}>
{this.state.screens.length > 0 && (
<TabView
ref={this.props.innerRef}
lazy={true}
swipeEnabled={false}
navigationState={this.state}
renderScene={this.state.screens}
renderTabBar={this.renderTabBar}
onIndexChange={this.handleIndexChange}
/>
)}
</View>
);
}
}

onPress not workin in a FlatList - React Native

I am working in a regular app using github API and can't solve a problem.
On my FlatList I am trying to implement an onPress to enter an Webview but this onPress
is not working for some reason. I tried everything. Now I just put a console.log and still not working. Code bellow:
import React, {Component} from 'react';
import {ActivityIndicator} from 'react-native';
import PropTypes from 'prop-types';
import api from '../../services/api';
import {
Container,
Header,
Avatar,
Name,
Bio,
Stars,
Starred,
OwnerAvatar,
Info,
Title,
Author,
Loading,
} from './styles';
export default class User extends Component {
static navigationOptions = ({navigation}) => ({
title: navigation.getParam('user').name,
});
static propTypes = {
navigation: PropTypes.shape({
getParam: PropTypes.func,
}).isRequired,
};
state = {
stars: [],
loading: false,
page: 1,
end: false,
refreshing: false,
};
async componentDidMount() {
this.loadItems();
}
loadItems = async (page = 1) => {
const {stars} = this.state;
const {navigation} = this.props;
const user = navigation.getParam('user');
this.setState({loading: true});
const response = await api.get(`/users/${user.login}/starred?page=`, {
params: {page},
});
this.setState({
stars: page >= 2 ? [...stars, ...response.data] : response.data,
loading: false,
page: response.data.length == 0 ? page - 1 : page,
end: response.data.length == 0 ? true : false,
refreshing: false,
});
};
loadMore = async () => {
const {page, end} = this.state;
const pageNum = page + 1;
{
!end ? this.loadItems(pageNum) : '';
}
};
refreshList = () => {
this.setState({refreshing: true, stars: []}, this.loadItems);
};
// Enviar repository via navigate
handleNavigate = repository => {
console.log('navi');
const {navigation} = this.props;
navigation.navigate('Repository', {repository});
};
teste = () => {
console.log('testado...');
};
render() {
const {navigation} = this.props;
const {stars, end} = this.state;
const user = navigation.getParam('user');
return (
<Container>
<Header>
<Avatar source={{uri: user.avatar}} />
<Name>{user.name}</Name>
<Bio>{user.bio}</Bio>
</Header>
<Stars
onRefresh={this.refreshList}
refreshing={this.state.refreshing}
data={stars}
onEndReachedThreshold={0.2}
onEndReached={this.loadMore}
keyExtractor={star => String(star.id)}
ListFooterComponent={
!end ? () => <ActivityIndicator size="large" color="#00ff00" /> : ''
}
renderItem={({item}) => (
** <Starred onPress={() => console.log('clicked')}> **
<OwnerAvatar source={{uri: item.owner.avatar_url.toString()}} />
<Info>
<Title>{item.name}</Title>
<Author>{item.owner.login}</Author>
</Info>
</Starred>
)}
/>
</Container>
);
}
}
Could you please try help me figure out what may be wrong? I just wanted to do this console.log but not even this is working.
The problem was that I did not stated that Starred was an button, that is the reason the onPress was not working.
Thank you #Huỳnh Lợi Nguyễn for the tip!

Getting "Can't perform a React state update on an unmounted component" when switching between screens

When switching between the Home.js and Chat.js files, I get this warning: "Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in the componentWillUnmount method". I removed the only listener that's on Chat.js and tried only setting state when the component is mounted in Home.js and removing it on unmount but I still get this warning.
Home.js
import React, { Component } from "react";
import { View, FlatList } from "react-native";
import { ListItem } from "react-native-elements";
import fireStoreDB from "../database/FirestoreDB";
let _isMounted = false;
export default class Home extends Component {
constructor(props) {
super(props);
this.state = {
usersInfo: [],
refreshing: false
};
}
componentDidMount() {
_isMounted = true;
this.LoadUsers();
}
componentWillUnmount() {
_isMounted = false;
}
LoadUsers = () => {
fireStoreDB
.getAllUsersExceptCurrent()
.then(users =>
Promise.all(
users.map(({ id, username, avatar }) =>
fireStoreDB
.getUserLastMessage(fireStoreDB.getUID, id)
.then(message => ({ id, username, avatar, message }))
)
)
)
.then(users => {
if (_isMounted) {
this.setState({
usersInfo: users.filter(x => typeof x.avatar !== "undefined"),
refreshing: false
});
}
});
};
renderItem = ({ item }) => (
<ListItem
onPress={() => {
this.props.navigation.navigate("Chat", {
userTo: item.id,
UserToUsername: item.username,
LoadUsers: this.LoadUsers
});
}}
title={item.username}
subtitle={item.message}
leftAvatar={{ source: { uri: item.avatar } }}
bottomDivider
chevron
/>
);
render() {
return (
<View>
<FlatList
data={this.state.usersInfo}
renderItem={this.renderItem}
keyExtractor={item => item.id}
refreshing={this.state.refreshing}
onRefresh={() => {
this.setState({ refreshing: true });
this.LoadUsers();
}}
/>
</View>
);
}
}
Chat.js
import React, { Component } from "react";
import { View, KeyboardAvoidingView } from "react-native";
import { HeaderBackButton } from "react-navigation-stack";
import { GiftedChat } from "react-native-gifted-chat";
import * as Progress from "react-native-progress";
import fireStoreDB from "../database/FirestoreDB";
const Themes = {
primaryTheme: "#30D921",
secondaryTheme: "#B32D83",
layoutTheme: "#c0c0c0"
};
export default class Chat extends Component {
static navigationOptions = ({ navigation }) => ({
title: navigation.getParam("UserToUsername"),
headerLeft: (
<HeaderBackButton
onPress={() => {
navigation.state.params.LoadUsers();
navigation.goBack();
}}
/>
)
});
constructor(props) {
super(props);
this.state = {
messages: [],
userToId: this.props.navigation.getParam("userTo")
};
}
componentDidMount() {
fireStoreDB.getMessages(
message =>
this.setState(previousState => ({
messages: GiftedChat.append(previousState.messages, message)
})),
this.chatId
);
}
componentWillUnmount() {
fireStoreDB.removeSnapshotListener(this.chatId);
}
// gifted chat user props
get user() {
return {
_id: fireStoreDB.getUID,
name: fireStoreDB.getName,
avatar: fireStoreDB.getAvatar
};
}
// merge ids between two parties for one to one chat
get chatId() {
const userFromId = fireStoreDB.getUID;
const chatIdArray = [];
chatIdArray.push(userFromId);
chatIdArray.push(this.state.userToId);
chatIdArray.sort(); // prevents other party from recreating key
return chatIdArray.join("_");
}
render() {
if (this.state.messages.length === 0) {
return (
<View
style={{
alignItems: "center",
marginTop: 260
}}
>
<Progress.Bar indeterminate color={Themes.primaryTheme} />
</View>
);
}
return (
<View style={{ flex: 1 }}>
<GiftedChat
messages={this.state.messages}
onSend={messages => fireStoreDB.sendMessages(messages, this.chatId)}
user={this.user}
/>
<KeyboardAvoidingView behavior="padding" keyboardVerticalOffset={80} />
</View>
);
}
}
FirestoreDB.js
removeSnapshotListener = chatId => {
firebase
.firestore()
.collection("messages")
.doc(chatId)
.collection("chats")
.orderBy("createdAt")
.onSnapshot(() => {});
};
UPDATE:
With your implementation, you cannot unsubribe messages collection.
You could try to return unsubscribe function from getMessages, then use it in componentWillUnmount
FirestoreDB.js
getMessages = (callback, chatId) => {
return firebase
.firestore()
.collection("messages")
.doc(chatId)
.collection("chats")
.orderBy("createdAt")
.onSnapshot(callback);
}
Chat.js
componentDidMount() {
this.unsubcribe = fireStoreDB.getMessages(
message =>
this.setState(previousState => ({
messages: GiftedChat.append(previousState.messages, message)
})),
this.chatId
);
}
componentWillUnmount() {
this.unsubcribe();
}

React with Redux: Child component does not rerender after props have changed (even though they are not shallow equal)

I'm building an app with React Native using Redux for the state management. I will post my code for all the involved components and the reducer down below, but since that is going to be much, let me describe the problem in a few sentences first.
I have an immutable reducer for my objects called 'waitercalls'. I have a screen (HomeScreen) that renders two components. Each component is a <FlatList /> of objects. The objects (waitercalls) are given to them via props by it's parent (HomeScreen). HomeScreen is connected to Redux via React-Redux' connect() and gets the objects ('waitercalls') via a selector created with Re-Select.
The left list's items can be pressed and upon press dispatch an event to the reducer. Here comes the problem. When the left list's item are pressed, the left list correctly updates (calls render()). The right list though does not re-render, even though it gets the same props.
Why does the left list rerender, but the right list not? The reducer is immutable, the selector is too and even the length of the list changes from one to zero which should eliminate the possibility of a shallow equal.
And now for the code:
waitercallsReducer:
import { createSelector } from "reselect";
const initialState = {};
const waitercallsReducer = (state = initialState, action) => {
if (action.payload && action.payload.entities && action.payload.entities.waitercalls) {
return {
...state,
...action.payload.entities.waitercalls
};
} else {
return state;
}
};
export default waitercallsReducer;
export const getAllWaitercallsNormalizedSelector = state => state.waitercalls;
export const getAllWaitercallsSelector = createSelector(
getAllWaitercallsNormalizedSelector,
waitercalls => Object.values(waitercalls)
);
export const getAllActiveWaitercallsSelector = createSelector(
getAllWaitercallsSelector,
waitercalls => waitercalls.filter(waitercall => !waitercall.done)
);
Action creators:
import { setValues } from "../core/core";
// feature name
export const WAITERCALLS = "[Waitercalls]";
// action creators
export const setValues = (values, type) => ({
type: `SET ${type}`,
payload: values,
meta: { feature: type }
});
export const setWaitercalls = waitercalls => setValues(waitercalls, WAITERCALLS);
HomeScreen:
import React, { Component } from "react";
import { View, TouchableOpacity } from "react-native";
import { SafeAreaView } from "react-navigation";
import { connect } from "react-redux";
import { Icon } from "react-native-elements";
import PropTypes from "prop-types";
// ... I've omitted all the imports so that it's shorter
export class HomeScreen extends Component {
// ... I've omitted navigationOptions and propTypes
render() {
const {
checkins,
customChoiceItems,
menuItemPrices,
menuItems,
orders,
pickedRestaurant,
tables,
waitercalls
} = this.props;
console.log("Rendering HomeScreen");
return (
<SafeAreaView style={styles.container}>
<View style={styles.activeOrders}>
<OrdersList
checkins={checkins}
customChoiceItems={customChoiceItems}
menuItemPrices={menuItemPrices}
menuItems={menuItems}
orders={orders}
restaurantSlug={pickedRestaurant.slug}
tables={tables}
waitercalls={waitercalls}
/>
</View>
<View style={styles.tableOvewView}>
<TableOverview
checkins={checkins}
orders={orders}
tables={tables}
waitercalls={waitercalls}
/>
</View>
</SafeAreaView>
);
}
}
const mapStateToProps = state => ({
checkins: getAllCheckinsSelector(state),
customChoiceItems: getAllCustomChoiceItemsNormalizedSelector(state),
menuItemPrices: getAllMenuItemPricesNormalizedSelector(state),
menuItems: getAllMenuItemsNormalizedSelector(state),
orders: getActiveOrdersSelector(state),
pickedRestaurant: getPickedRestaurantSelector(state),
tables: getAllTablesSelector(state),
waitercalls: getAllActiveWaitercallsSelector(state)
});
export default connect(mapStateToProps)(HomeScreen);
OrdersList (as you can see OrdersList also allows presses for orders, which displays the same erroneous behaviour of not having the TableOverView rerender), which is the left list with the clickable <ListItem />s.
import React, { PureComponent } from "react";
import { FlatList, Image, Text } from "react-native";
import { ListItem } from "react-native-elements";
import { connect } from "react-redux";
import PropTypes from "prop-types";
// ... omitted imports
export class OrdersList extends PureComponent {
// omitted propTypes
keyExtractor = item => item.uuid;
registerItem = item => {
// Remember the order status, in case the request fails.
const { restaurantSlug, setOrders } = this.props;
const itemStatus = item.orderStatus;
const data = {
restaurant_slug: restaurantSlug,
order_status: "registered",
order_uuid: item.uuid
};
setOrders({
entities: { orders: { [item.uuid]: { ...item, orderStatus: data.order_status } } }
});
postOrderStatusCreate(data)
.then(() => {})
.catch(err => {
// If the request fails, revert the order status change and display an alert!
alert(err);
setOrders({ entities: { orders: { [item.uuid]: { ...item, orderStatus: itemStatus } } } });
});
};
answerWaitercall = item => {
const { restaurantSlug, setWaitercalls } = this.props;
const data = {
done: true,
restaurant_slug: restaurantSlug
};
setWaitercalls({ entities: { waitercalls: { [item.uuid]: { ...item, done: true } } } });
putUpdateWaitercall(item.uuid, data)
.then(() => {})
.catch(err => {
alert(err);
setWaitercalls({ entities: { waitercalls: { [item.uuid]: { ...item, done: false } } } });
});
};
renderItem = ({ item }) => {
const { checkins, customChoiceItems, menuItemPrices, menuItems, tables } = this.props;
return item.menuItem ? (
<ListItem
title={`${item.amount}x ${menuItems[item.menuItem].name}`}
leftElement={
<Text style={styles.amount}>
{tables.find(table => table.checkins.includes(item.checkin)).tableNumber}
</Text>
}
rightTitle={`${
menuItemPrices[item.menuItemPrice].label
? menuItemPrices[item.menuItemPrice].label
: menuItemPrices[item.menuItemPrice].size
? menuItemPrices[item.menuItemPrice].size.size +
menuItemPrices[item.menuItemPrice].size.unit
: ""
}`}
subtitle={`${
item.customChoiceItems.length > 0
? item.customChoiceItems.reduce((acc, customChoiceItem, index, arr) => {
acc += customChoiceItems[customChoiceItem].name;
acc += index < arr.length - 1 || item.wish ? "\n" : "";
return acc;
}, "")
: null
}${item.wish ? "\n" + item.wish : ""}`}
onPress={() => this.registerItem(item)}
containerStyle={styles.alignTop}
bottomDivider={true}
/>
) : (
<ListItem
title={
item.waitercallType === "bill"
? SCREEN_TEXT_HOME_BILL_CALLED
: SCREEN_TEXT_HOME_SERVICE_ASKED
}
leftElement={
<Text style={styles.amount}>
{
tables.find(table =>
table.checkins.includes(
checkins.find(checkin => checkin.consumer === item.consumer).uuid
)
).tableNumber
}
</Text>
}
rightIcon={{
type: "ionicon",
name: item.waitercallType === "bill" ? "logo-euro" : "ios-help-circle-outline"
}}
onPress={() => this.answerWaitercall(item)}
bottomDivider={true}
/>
);
};
render() {
const { orders, waitercalls } = this.props;
return (
<FlatList
keyExtractor={this.keyExtractor}
data={[...orders, ...waitercalls]}
renderItem={this.renderItem}
// ... omitted ListHeader and ListEmpty properties
/>
);
}
}
export default connect(
null,
{ setOrders, setWaitercalls }
)(OrdersList);
TableOverview, which is the right <FlatList />:
import React, { Component } from "react";
import { FlatList } from "react-native";
import PropTypes from "prop-types";
// ... omitted imports
export class TableOverview extends Component {
// ... omitted propTypes
keyExtractor = item => item.uuid;
renderItem = ({ item }) => {
const { checkins, orders, waitercalls } = this.props;
if (item.invisible) return <Table table={item} />;
console.log("Rendering TableOverview");
return (
<Table
table={item}
hasActiveOrders={orders.some(order => item.userOrders.includes(order.uuid))}
billWanted={item.checkins.some(checkin =>
waitercalls.some(
waitercall =>
waitercall.waitercallType === "bill" &&
waitercall.consumer ===
checkins.find(checkinObj => checkinObj.uuid === checkin).consumer
)
)}
serviceWanted={item.checkins.some(checkin =>
waitercalls.some(
waitercall =>
waitercall.waitercallType === "waiter" &&
waitercall.consumer ===
checkins.find(checkinObj => checkinObj.uuid === checkin).consumer
)
)}
/>
);
};
formatData = (data, numColumns) => {
const numberOfFullRows = Math.floor(data.length / numColumns);
let numberOfElementsLastRow = data.length - numberOfFullRows * numColumns;
while (numberOfElementsLastRow !== numColumns && numberOfElementsLastRow !== 0) {
data.push({ uuid: `blank-${numberOfElementsLastRow}`, invisible: true });
numberOfElementsLastRow++;
}
return data;
};
render() {
const { tables } = this.props;
return (
<FlatList
style={styles.container}
keyExtractor={this.keyExtractor}
data={this.formatData(tables, NUM_COLUMNS)}
renderItem={this.renderItem}
numColumns={NUM_COLUMNS}
/>
);
}
}
export default TableOverview;
I found the solution!
The List was not rerendering, because the <FlatList /> only looked at the tables and not the waitercalls.
I had to add the following property to the <FlatList />:
extraData={[...checkins, ...orders, ...waitercalls]}

Access passed data with StackNavigation outside render

I'm able to fetch a ListView and show details page onPress of any of the list item. I can show the details of the clicked item in the DetailsPage but only in the render(). How to access any of the value outside of the render? I want to use that value to fetch information from another API
Main Page:
import React, { Component } from 'react';
import {
AppRegistry, StyleSheet, ListView,
Text, TouchableHighlight, View
} from 'react-native';
import { StackNavigator } from 'react-navigation';
import DetailsPage from './src/DetailsPage';
class HomeScreen extends React.Component {
static navigationOptions = {
title: 'MyApp!',
};
constructor() {
super();
const ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
this.state = {
userDataSource: ds,
};
}
componentDidMount(){
this.fetchUsers();
}
fetchUsers(){
fetch('https://jsonplaceholder.typicode.com/users')
.then((response) => response.json())
.then((response) => {
this.setState({
userDataSource: this.state.userDataSource.cloneWithRows(response)
});
});
}
renderRow(user, sectionID, rowID, highlightRow){
const { navigate } = this.props.navigation;
return(
<TouchableHighlight onPress={() => navigate('DetailsPage', {users:user })}>
<View style={styles.row}>
<Text style={styles.rowText}> {user.name} </Text>
</View>
</TouchableHighlight>
)
}
render(){
return(
<ListView
dataSource = {this.state.userDataSource}
renderRow = {this.renderRow.bind(this)}
/>
)
}
}
const NavigationTest = StackNavigator({
Home: { screen: HomeScreen },
DetailsPage: { screen:DetailsPage },
});
AppRegistry.registerComponent('NavigationTest', () => NavigationTest);
Details Page:
import React, { Component } from 'react';
import { StyleSheet, ListView, Text, TouchableHighlight, View } from 'react-native';
export default class DetailsPage extends React.Component {
static navigationOptions = ({ navigation }) => ({
title: `${navigation.state.params.users.name}`,
});
// var userid = 2; --> This doesn't work as it returns Unexpected Token where var is mentioned.
constructor() {
super();
const ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
this.state = {
albumDataSource: ds,
};
}
componentDidMount(){
this.fetchAlbums();
}
fetchAlbums(){
var theUser = 2; //This is the value I want to receive from the clicked user.
// var newUser = this.props.navigation.state.users.id; -> this doesnt work.
fetch('https://jsonplaceholder.typicode.com/albums?userId='+newUser)
.then((response) => response.json())
.then((response) => {
this.setState({
albumDataSource: this.state.albumDataSource.cloneWithRows(response)
});
});
}
renderRow(album, sectionID, rowID, highlightRow){
return(
<TouchableHighlight>
<View style={styles.row}>
<Text style={styles.rowText}> {album.userId} - {album.title} </Text>
</View>
</TouchableHighlight>
)
}
render() {
const { params } = this.props.navigation.state;
return (
<View style={styles.container}>
<Text style={styles.textstyle}>Screen Chat with {params.users.name}</Text>
<Text style={styles.textstyle}>Username : {params.users.username}</Text>
<Text style={styles.textstyle}>Email : {params.users.email}</Text>
<Text style={styles.textstyle}>ID : {params.users.id}</Text>
<ListView
dataSource = {this.state.albumDataSource}
renderRow = {this.renderRow.bind(this)}
/>
</View>
);
}
}
So I want to use the users.id to fetch more data on the DetailsPage and display that data. How do I do that. Please help. Many thanks.
Here what i have found , this look wrong to me,
var newUser = this.props.navigation.state.users.id;
Use this may be it can help you
console.log(this.props.naviagtion.state.params) **Check if are getting those value then use below one **
var newUser = this.props.navigation.state.params.users.id;

Resources