React not rendering component after componentDidMount - reactjs

I have an Component, which is no rerendering after componentDidMount.
The render Method is looking like this :
render() {
{
console.log("----------RENDERING-----------------------------")
}
return (
<ImageBackground
source={require('../assets/images/bg.png')}
style={styles.bg}
>
<View style={styles.containerHome}>
<View style={styles.top}>
<City/>
<Text>myapp</Text>
{/*<Filters />*/}
</View>
<CardStack
loop={true}
verticalSwipe={false}
renderNoMoreCards={() => null}
ref={swiper => (this.swiper = swiper)}
>
{this.state.data.map((item, index) => (
<Card key={index}>
<CardItem
text={item.name}
detail={item.detail}
imageurl={item.imageurl}
matches="0"
actions
onPressLeft={() => this.swiper.swipeLeft()}
onPressRight={() => this.swiper.swipeRight()}
/>
</Card>
))}
</CardStack>
</View>
</ImageBackground>
);
}
...simply rendering a card stack.
Relevant here is this line :
this.state.data.map((item, index) => (
If i set the Data static from a file (Demo), it is working!
means if the line is looking like this
Demo.map((item, index) => (
everything alright!
but when i set the data in componentDidMount, it is not working!
I really dont know what react-native is doing here :
componentDidMount() {
this.setState({
isLoaded: true,
data: Demo
});
I set the state.data to exactly the same Demo Values, but react is not rerendering.
It seems to be that this.state.data is always empty.
Maybe anyone can help me?
Thx so much

ComponentDidMount() executes after the render() function, so you had better do this before rendering and outside of ComponentDidMount():
this.setState({
isLoaded: true,
data: Demo
});
So initially, before render(), you have to set some value of data.
Try with three possible answers:
Default value {data:Demo}, or
Implement this.state in a function which can be executed before render(), or
Put it in the render() function before the return statement.

Thx so much for the hint.
But i have already problems. Seems that i dont get the lifecylce, even when i am programming now react for a liitle bit.
Your hint was excellent, when i do it in the constructor, it is working.
But in the end, i wann fetch the data there, and if i do this, it doesnt seems to work in the constructor.
fetch('http://hostname/api/v1/xxxx', {
method: 'get',
headers: new Headers({
'Authorization': 'Bearer pumuckl',
'Content-Type': 'application/json'
}
)
}).then(res => res.json())
.then(
(result) => {
this.state = {
data: Demo,
}
},
// Note: it's important to handle errors here
// instead of a catch() block so that we don't swallow
// exceptions from actual bugs in components.
(error) => {
this.setState({
isLoaded: true,
error
});
}
)
the code is from the facebook documentation! Fetch is working!
What i am doing here is setting the state to the Demo Data, just to see if the lifecylce is waiting for the constructor and it seems that it doesn't.
Seems that rendering is be triggered before the constructor has finished initializing (..i can not imagine, that would be really bad), but i get a null Exception in the List!
Do i have to work with async await? I dont think so.
Just wanna initialze my List before rendering from a fetch.
Absolutely strange.
so if you look in my logs how the lifecycle is processing :
10-28 17:44:06.847 4796 5362 I ReactNativeJS: *************************** Constructor *****************************************************
10-28 17:44:06.851 4796 5362 I ReactNativeJS: ----------RENDERING-----------------------------
10-28 17:44:06.918 4796 5362 I ReactNativeJS: *************************** component Did Mount *****************************************************
10-28 17:44:06.927 4796 5362 I ReactNativeJS: ----------RENDERING-----------------------------
10-28 17:44:06.935 4796 5362 I ReactNativeJS: *************************** component Did Update *****************************************************
I am really a little bit desperate at the moment....
when i log my data in the rendering method :
render() {
const data = this.state.data
{
console.log("----------RENDERING-----------------------------")
console.log("----------DATA IN RENDERING-----------------------------")
console.log(data)
}
return ( ...
actually, the data seem be there. But using
{data.map((item, index) => (
does not work, while
{Demo.map((item, index) => (
is working.
I really dont know what going on here?

Related

Loading data on screen load

I have following code, Right now renderProductItem is rendered with fixed products. I want list to be rendered on screen load. So when screen is loaded it should call an API and render the list based on API response.
I saw solutions using state sopmething like https://github.com/vikrantnegi/react-native-searchable-flatlist/blob/master/src/SearchableList.js but the problem is when i create constructer its not getting called on screen load. So i am not sure how to use state in my case.
I am unable to figure out how to call an API on screen load and render list once response is available.
export const ProductListScreen = ({ navigation, route }): React.ReactElement => {
const displayProducts: Product[] = products.filter(product => product.category === route.name);
const renderProductItem = (info: ListRenderItemInfo<Product>): React.ReactElement => (
<Card
style={styles.productItem}
header={() => renderItemHeader(info)}
footer={() => renderItemFooter(info)}
onPress={() => onItemPress(info.index)}>
<Text category='s1'>
{info.item.title}
</Text>
<Text
appearance='hint'
category='c1'>
{info.item.category}
</Text>
<RateBar
style={styles.rateBar}
value={4}
// onValueChange={setRating}
/>
<CategoryList
style={styles.categoryList}
data={["Adventure", "Sport", "Science", "XXX"]}
/>
<Text>
The element above represents a flex container (the blue area) with three flex items.
</Text>
</Card>
);
return (
<List
contentContainerStyle={styles.productList}
data={displayProducts.length && displayProducts || products}
renderItem={renderProductItem}
/>
);
};
You can use hooks in your ProductListScreen component. You can create a state using useState hook and with the help of useEffect you achieve the behaviour of componentDidMount.
Please refer to this link:
https://reactjs.org/docs/hooks-effect.html
Use componentDidMount() to display the content. In React, this is a "lifecycle method". In the examples cited in the documentation you see that functions can be triggered when a component is added or removed. Based on your description you would want to test out componentDidMount for your code.
In the code sample you cited, you can see that this developer uses it in his class to call the makeRemoteRequest function
componentDidMount() {
this.makeRemoteRequest();
}
makeRemoteRequest = () => {
const url = `https://randomuser.me/api/?&results=20`;
this.setState({ loading: true });
fetch(url)
.then(res => res.json())
.then(res => {
this.setState({
data: res.results,
error: res.error || null,
loading: false,
});
this.arrayholder = res.results;
})
.catch(error => {
this.setState({ error, loading: false });
});
};

setState() block the UI when two setState() run

Here is my componentDidMount() method :
componentDidMount() {
const subscription = accelerometer.subscribe(({ x, y, z, timestamp }) => {
x = Math.trunc(x*100);
this.setState({x})
});
}
In above method, every 100 millisecond state is changing. I used that state in my render() method as below :
render() {
const animatedImageStyle = StyleSheet.flatten([
styles.captureButton,
{
transform: [{rotateZ:this.state.x + 'deg'}]
}
])
return (
<SideMenu
menu={leftMenu}
isOpen={this.state.isOpenLeftMenu}
menuPosition={'left'}
bounceBackOnOverdraw={false}
onChange={(isOpenLeftMenu) => this.updateLeftMenuState(isOpenLeftMenu)}
>
<View>
<TouchableOpacity
activeOpacity={0.5}
onPress={(this.state.recordingMode == 'camera')?() => this.takePicture():() => this.toggleRecording()}
>
<Image
source={require('../assets/imgs/forRotate.png')}
style={animatedImageStyle}
/>
</TouchableOpacity>
</View>
</SideMenu>
)
}
Now, the problem is that when I trying to open sidemenu, it is not opening, I mean it opening but hanging too much. My whole app hanging too much.
I think that's because of below method :
updateLeftMenuState(isMenuOpen) {
this.setState({
isOpenLeftMenu:isMenuOpen
})
}
Notice that I am updating another state called isOpenLeftMenu, which may blocked during I update state x.
Can anyone tell me what't going wrong here ?
you can move the animation view in a separate component along with subscription logic. So the state update of that component won't affect the SideMenu component.

How do I render an object in react native?

Working on pulling data from an external API (FlightStats).
Currently the data fetch is working as it finds the childs of the parent request. Now stuck rendering through an array problem.
Tried multiple options for the request and data source options
Request from API:
componentDidMount() {
fetch('https://api.flightstats.com/flex/schedules/rest/v1/json/flight/AA/100/departing/2019/3/24?appId=XXXXX&appKey=+XXXXX')
.then((response) => response.json())
.then((response) => {
this.setState({
request: response.request
})
})
.catch((error) => {
console.log(error)
});
}
Constructor:
constructor() {
super();
this.state = {
request: 'carrier'
}
}
Render:
<View style={Global.container}>
<Text>{this.state.request.carrier}</Text>
{/* //={[{ key: 'a'}, { key: 'b'}]}
//renderItem={({item }) => <Text>{item.key}</Text>} */}
</View>
Data result in Json
{"request":{"carrier":{"requestedCode":"AA","fsCode":"AA"},"codeType":{},"flightNumber":{"requested":"100","interpreted":"100"},"departing":true,"date":{"year":"2019","month":"3","day":"24","interpreted":"2019-03-24"},"url":"https://api.flightstats.com/flex/schedules/rest/v1/json/flight/AA/100/departing/2019/3/24"},"scheduledFlights":[{"carrierFsCode":"AA","flightNumber":"100","departureAirportFsCode":"JFK","arrivalAirportFsCode":"LHR","stops":0,"departureTerminal":"8","arrivalTerminal":"3","departureTime":"2019-03-24T19:40:00.000","arrivalTime":"2019-03-25T06:50:00.000","flightEquipmentIataCode":"77W","isCodeshare":false,"isWetlease":false,"serviceType":"J","serviceClasses":["R","F","J","Y"],"trafficRestrictions":[],"codeshares":[{"carrierFsCode":"AY","flightNumber":"4012","serviceType":"J","serviceClasses":["F","J","Y"],"trafficRestrictions":[],"referenceCode":1139031},{"carrierFsCode":"BA","flightNumber":"1511","serviceType":"J","serviceClasses":["R","F","J","Y"],"trafficRestrictions":[],"referenceCode":1250367},{"carrierFsCode":"GF","flightNumber":"6654","serviceType":"J","serviceClasses":["J","Y"],"trafficRestrictions":["Q"],"referenceCode":2204628},{"carrierFsCode":"IB","flightNumber":"4218","serviceType":"J","serviceClasses":["R","F","J","Y"],"trafficRestrictions":[],"referenceCode":2305895},{"carrierFsCode":"LY","flightNumber":"8051","serviceType":"J","serviceClasses":["F","J","Y"],"trafficRestrictions":["Q"],"referenceCode":2942513}],"referenceCode":"807-470028--"}],"appendix":{"airlines":[{"fs":"AA","iata":"AA","icao":"AAL","name":"American Airlines","phoneNumber":"08457-567-567","active":true},{"fs":"LY","iata":"LY","icao":"ELY","name":"El Al","phoneNumber":"+ 972-3-9771111","active":true},{"fs":"AY","iata":"AY","icao":"FIN","name":"Finnair","phoneNumber":"+ 358 600 140 140","active":true},{"fs":"IB","iata":"IB","icao":"IBE","name":"Iberia","phoneNumber":"1800 772 4642","active":true},{"fs":"BA","iata":"BA","icao":"BAW","name":"British Airways","phoneNumber":"1-800-AIRWAYS","active":true},{"fs":"GF","iata":"GF","icao":"GFA","name":"Gulf Air","phoneNumber":"973 17 335 777","active":true}],"airports":[{"fs":"JFK","iata":"JFK","icao":"KJFK","faa":"JFK","name":"John F. Kennedy International Airport","street1":"JFK Airport","city":"New York","cityCode":"NYC","stateCode":"NY","postalCode":"11430","countryCode":"US","countryName":"United States","regionName":"North America","timeZoneRegionName":"America/New_York","weatherZone":"NYZ178","localTime":"2019-03-24T00:55:59.327","utcOffsetHours":-4.0,"latitude":40.642335,"longitude":-73.78817,"elevationFeet":13,"classification":1,"active":true},{"fs":"LHR","iata":"LHR","icao":"EGLL","name":"London Heathrow Airport","city":"London","cityCode":"LON","stateCode":"EN","countryCode":"GB","countryName":"United Kingdom","regionName":"Europe","timeZoneRegionName":"Europe/London","localTime":"2019-03-24T04:55:59.327","utcOffsetHours":0.0,"latitude":51.469603,"longitude":-0.453566,"elevationFeet":80,"classification":1,"active":true}],"equipments":[{"iata":"77W","name":"Boeing 777-300ER","turboProp":false,"jet":true,"widebody":true,"regional":false}]}}
Error Message:
Invariant Violation: Objects are not valid as a React child (found: object with keys {resquestedCode, fsCode}). If you meant to render a collection of childen, use an array instead.
So this is where I am stuck. The initial fetching is working and finding the sub children. For some reason not sure why I cannot render the items or just display the results from the json.
Any help or tutorials will do.
Thanks again
carrier is an object in your JSON data and hence you cannot print it directly. If you want to print it as a string, please do this.
<Text>{JSON.stringify(this.state.request.carrier)}</Text>
If you want it to look neat, you can format it like this.
<Text>{JSON.stringify(this.state.request.carrier, 0, 4)}</Text>

React-Table not loading API data with server-side options enabled

I am using react-table version 6.9.2 to connect to an API and display the data. My initial implementation worked fine:
componentDidMount() {
axios
.get('http://jsonplaceholder.typicode.com/posts', {
responseType: 'json'
})
.then((response) => {
this.setState({ posts: response.data });
});
}
return (
<ReactTable
columns={columns}
data={this.state.posts}
filterable
defaultPageSize={5}
noDataText={'Loading...'}
/>
);
However I want to scale up my application and connect to a database and enable server side pagination. I followed the example provided:
https://github.com/tannerlinsley/react-table/tree/v6#server-side-data
However the data is not being displayed when I implemented the below changes to my ReactTable
<ReactTable
columns={columns}
data={this.state.posts}
pages={this.state.pages}
loading={this.state.loading}
filterable
defaultPageSize={5}
noDataText={"Loading..."}
manual // informs React Table that you'll be handling sorting and pagination server-side
onFetchData={(state, instance) => {
// show the loading overlay
this.setState({ loading: true });
// fetch your data
axios
.post("http://jsonplaceholder.typicode.com/posts", {
page: state.page,
pageSize: state.pageSize,
sorted: state.sorted,
filtered: state.filtered
})
.then(res => {
// Update react-table
this.setState({
posts: res.data,
data: res.data.posts,
pages: res.data.pages,
loading: false
});
});
}}
/>
I believe I am messing up with the onFetchData function but I am not entirely sure as to what. Is there a better way to enable this? Any help would be appreciated!
I've got a working code sandbox here: https://codesandbox.io/s/yp88v0kx2z
please make few corrections in urls,callback and axios
https://codesandbox.io/s/lrn7j5vjrl?fontsize=14

Grandchild component not changing grandparent state

There is a button 2 layers deep in a NavigatorIOS that when triggered, should change the TabBarIOS selected TabBarIOS Item.
The components are structured as follows:
--FooterTabs
------NavigatorIOS:List -> ListItem
I am attempting to do the above by having a function inside FooterTabs that changes the state, and having TabBar.Items whose prop 'selected' becomes true when the state's 'selectedTab'=== different strings.
Like so:
_changeToAlarms(){
console.log('Hello from Footer Tabs');
this.setState({
selectedTab: 'Alarms'
});
}
render(){
return(
<Icon.TabBarItemIOS title={'Alarms'}
iconName='ios-clock'
selected={this.state.selectedTab === 'Alarms'}
onPress={()=> {
this.setState({
selectedTab: 'Alarms'
});
}}>
<ComingSoon/>
</Icon.TabBarItemIOS>
<Icon.TabBarItemIOS title={'Schedules'}
iconName='ios-moon'
selected={this.state.selectedTab === 'Schedules'}
onPress={()=> {
this.setState({
selectedTab: 'Schedules'
});
}}>
</Icon.TabBarItemIOS>
);
}
*Icon.TabBatItem acts exactly like TabBarIOS.Item.
onPress works, but to be able to change the tab in a similar fashion (by modifying the component's state) I passed _changeToAlarms() as a prop to 'SleepSchedules'.
<Icon.TabBarItemIOS ...
>
<NavigatorIOS
initialRoute={{
component: SleepSchedules ,
title: ' ',
passProps: {changeToAlarms: ()=> this._changeToAlarms()}
}}
style={{flex: 1}}
/>
</Icon.TabBarItemIOS>
And from SleepSchedules, I am navigating to the next component and passing the previous'changeToAlarms' as a prop.
_handlePress(selectedSchedule){
this.setState({selectedSchedule});
this._navScheduleItem(selectedSchedule)
}
_navScheduleItem(scheduleName){
this.props.navigator.push({
title: `${scheduleName} Sleep`,
component: ScheduleItem,
passProps: {scheduleName}, changeToAlarms: ()=> this.props.changeToAlarms
})
}
render(){
return(
...
onPress={()=> this._handlePress('Monophasic')}>
);
}
And in ScheduleItem I am attempting to call the prop 'changeToAlarm' that was passed, which should be the one from Footer Tabs.
_handleTouch(){
console.log('Hello from Schedule Item');
this.props.changeToAlarms;
}
render(){
return(
...
onPress={()=> this._handleTouch()}
);
}
The console logs 'Hello from ScheduleItem' every time I press it, but doesn't log 'Hello from FooterTabs' nor does it change the tab.
Does anyone spot an error?
I am a beginner, so thank you much for your help! :)
You need a () after this.props.changeToAlarms. this.props.changeToAlarms()
I think there might be a better approach but without seeing more code its hard to get the full picture of whats going on. On thing that did catch my eye was in your _handlePress function. You called setState and then another function.
According to ReactDocs:
There is no guarantee of synchronous operation of calls to setState
and calls may be batched for performance gains.
This might be causing an issue for you, again without more code its hard to tell. You can try using the overload method for setState that takes a function as the second arg.
setState(nextState, callback)
Performs a shallow merge of nextState into current state. This is the primary > method you use to trigger UI updates from event handlers and server request > > callbacks.
The first argument can be an object (containing zero or more keys to
update) or a function (of state and props) that returns an object
containing keys to update.
This ensures your setstate completes before your next function is executed.
_handlePress(selectedSchedule){
this.setState({selectedSchedule}, () =>
{
this._navScheduleItem(selectedSchedule);
});
}

Resources