React redux async mapStateToProps - javascript

How come when calling mapDispatchToProps functions in componentDidMount,
mapStateToProps totalDoctorCount: state.doctors.totalDoctorCount wont always load on time and I would get undefined result in console.log("this.props.totalDoctorCount: "+this.props.totalDoctorCount );.
I know it's the nature of async, but is there a way to fix it am i doing something wrong here.
Full Code :
doctorActions
export function getDoctors(filterType){
return function(dispatch){
axios.get("/api/doctors/"+filterType)
.then(function(response){
dispatch({type:"GET_DOCTORS",payload:response.data});
})
.catch(function(err){
dispatch({type:"GET_DOCTORS_REJECTED",payload:err});
})
}
}
export function getTotalDoctors(){
return function(dispatch){
axios.get("/api/getTotalDoctors/")
.then(function(response){
dispatch({type:"TOTAL_DOCTORS",payload:response.data});
console.log(response.data);
})
.catch(function(err){
//console.log(err);
dispatch({type:"TOTAL_DOCTORS_REJECTED",payload:"there was an error rortal doctors"});
})
}
}
doctorReducer
export function doctorsReducers(state={
doctors:[],
}, action){
switch(action.type){
case "GET_DOCTORS":
// return the state and copy of boos array from state
return {...state,doctors:[...action.payload]}
break;
case "TOTAL_DOCTORS":
// return the state and copy of boos array from state
return {
...state,
totalDoctorCount:action.payload
}
break;
}
return state;
}
server API
app.get('/doctors/:filterType',function(req,res){
let filterType = req.params.filterType;
var query = {};
if(filterType == "dateCreated"){
query = {date_created: 'desc'};
}else if(filterType == "dateUpdated"){
query = {date_updated: 'desc'};
}
Doctors.find({}).sort(query).limit(3).exec(function(err,doctors){
if(err){
throw err;
}
res.json(doctors);
});
});
app.get('/getTotalDoctors',function(req,res){
Doctors.count({}, function(err, count){
if(err){
throw err;
}
res.json(count);
});
});
component
class MainAdmin extends React.Component{
constructor(){
super();
this.state = {
selected_filter:"dateCreated"
};
}
openAddDoctorModal = () => {
this.setState({AddDoctorModal:true});
}
closeAddDoctorModal = () => {
this.setState({AddDoctorModal:false});
}
componentDidMount(){
this.props.getTotalDoctors();
this.props.getDoctors(this.state.selected_filter);
}
loadPage = (pageNum) => {
//alert(pageNum);
this.props.loadPage(pageNum,this.state.selected_filter);
}
render(){
const doctorsList = this.props.doctors.map(function(doctorsArr){
return(
<Col xs={12} sm={12} md={12} key={doctorsArr._id}>
<DoctorsItem
_id = {doctorsArr._id}
doc_fname = {doctorsArr.doc_fname}
doc_lname = {doctorsArr.doc_lname}
/>
</Col>
)
});
//const lengthPage = parseInt(this.props.totalDoctorCount/3);
console.log("this.props.totalDoctorCount2: "+this.props.totalDoctorCount );
const pages = parseInt(this.props.totalDoctorCount/3, 10);
console.log("pages: "+pages );
const pageNums = [...Array(pages)].map((pageNum, i) => {
return(
<Col xs={2} sm={2} md={2} key={i+1}>
<Button onClick={() => this.loadPage(i+1)} bsStyle="success" bsSize="small">
{i+1}
</Button>
</Col>
)
});
return(
<Well>
<Row style={{marginTop:'15px'}}>
{doctorsList}
</Row>
<Row style={{marginTop:'15px'}}>
{pageNums}
</Row>
</Well>
)
}
}
function mapStateToProps(state){
return{
doctors: state.doctors.doctors,
totalDoctorCount:state.doctors.totalDoctorCount
}
}
function mapDispatchToProps(dispatch){
return bindActionCreators({
getDoctors:getDoctors,
loadPage:loadPage,
getTotalDoctors:getTotalDoctors
},dispatch)
}
export default connect(mapStateToProps,mapDispatchToProps)(MainAdmin);

There are several ways you can handle this, but you must first understand how to handle asynchronous actions that affect your dom.
Whenever a component mounts (and depending on how you've set your app up, whenever a change is made to props, state, etc), its render function is called. In your example, the component mounts, then asks the server for the list of doctors, calls render(), and then receives the list of doctors from the server. To rephrase, by the time it called the render method, it has not yet received the list of doctors from the axios call.
Apologies if you understood all of this. Now for why this.props.totalDoctorCount is returning undefined: your app's state.totalDoctorCount is not being defined until the function getTotalDoctors resolves (i.e., hears back from server). You can fix this rather simply by defining totalDoctorCount as 0 in your defaultState (where you defined doctors as an empty array).
On the other hand, do you really want users to see/think that there are a total of 0 doctors until the server responds in time? This might be a good opportunity to consider a loading component. What I like to do is right below render(), check for the existence of whatever list you need to iterate through and if it is empty, you can return a LoadingComponent (you can make this on your own and use it wherever something needs to load).
This by itself is not enough, because you don't want the page to load indefinitely in the event that you actually don't have any doctors, so this LoadingComponent should only appear if the function that is retrieving the list that it's concerned with is still 'fetching'. So perhaps you can implement three actions that are called before you fetch, after the fetch is responded to, and if there is an error.
So to outline:
1) MainAdmin mounts.
2) GetDoctors and GetTotalDoctors are called.
3) A new action isFetching is called, leaving your state as:
{
doctors: [],
totalDoctors: 0, //assuming you have added this to defaultState
isFetchingDoctors: true
}
4) MainAdmin calls render().
5) since state.doctors is empty and state.isFetchingDoctors is true, MainAdmin.render() returns your new LoadingComponent.
6) Your server responds to your axios call with the list of doctors and the totalDoctorCount (note: this will happen at different times, but for sake of simplicity, I am treating them as happening together).
7) Your success handler updates your state with the new list of doctors:
{
doctors: [1, 2, 3],
totalDoctors: 3,
isFetchingDoctors: true
}
8) MainAdmin calls render() again because of the change in state, but because state.isFetchingDoctors is still true, it will still show LoadingComponent.
8) Your second new action isFetched() is called, leaving your state as:
{
doctors: [1, 2, 3],
totalDoctors: 3,
isFetchingDoctors: false
}
9) MainAdmin calls render() again, but this time the conditions to indicate that it is no longer loading are met, and you can safely iterate through your list of doctors.
One final note: You could also set isFetching to false in your reducer as soon as you GetDoctors but I personally like to separate the asynchronous status functions into their own function to keep to the motto of every function only tasked with doing one thing.

Related

How can manipulate redux data after dispatch it?

I have a search screen, contain Input And TopTabs "Songs, Artists",
When I get data from API after a search I make two things
1- I setState to appear the TopTab Component "true/false"
2- dispatch an action to save Songs & Artists Data in redux store.
that works fine.
But in topTab component, as I say before I have tow tabs "songs, artists"
For example, In the Songs component, I want to manipulate the data to achieve my case so in componentDidMount I Map the songs array from redux and push the new data into the component state.
But it's not working fine!
At the first time, I got songs from redux as empty [] although it's saved successfully in redux store when I get data from API
So how can I handle this case to not mutate the data?
Search.js "Main screen"
onSearch = async () => {
const {searchText} = this.state;
if (searchText.length > 0) {
this.setState({onBoarding: false}); // to appear the TopTab Component
try {
let response = await API.post('/search', {
name: searchText,
});
let {
data: {data},
} = response;
let artists = data.artists.data;
let songs = data.traks.data;
this.props.getResult(songs, artists);
}
catch (err) {
console.log(err);
}
}
render(){
<View style={styles.searchHeader}>
<Input
onChangeText={text => this.search(text)}
value={this.state.searchText}
onSubmitEditing={this.onSearch}
returnKeyType="search"
/>
</View>
{this.state.onBoarding ? (
<SearchBoard />
) : (
<SearchTabNavigator /> // TopTabs component
)}
}
SongsTab
...
componentDidMount() {
console.log('props.songs', this.props.songs); // Empty []
let All_tunes = [];
if (this.props.songs?.length > 0) {
console.log('mapping...');
this.props.songs.map(track =>
All_tunes.push({
id: track.id,
name: track.name,
url: URL + track.sounds,
img: URL + track.avatar,
}),
);
this.setState({All_tunes});
}
}
...
const mapStateToProps = state => {
return {
songs: state.searchResult.songs,
};
};
Edit
I fix the issue by using componentDidUpdate() life cycle
If you have any other ways tell me, please!
SongsTab
manipulateSongs = arr => {
let All_tunes = [];
arr.map(track =>
All_tunes.push({
id: track.id,
name: track.name,
url: URL + track.sounds,
img: URL + track.avatar,
}),
);
this.setState({All_tunes});
};
componentDidMount() {
if (this.props.songs?.length > 0) {
this.manipulateSongs(this.props.songs);
console.log('mapping...');
}
}
componentDidUpdate(prevProps) {
if (prevProps.songs !== this.props.songs) {
this.manipulateSongs(this.props.songs);
}
}
The problem you're referring to has to do with the way asynchronous code is handled in JavaScript (and in turn react-redux). When your component initially mounts, your redux store passes its initial state to your SongsTab.js component. That seems to be an empty array.
Any API call is an asynchronous action, and won't update the redux store until the promise has resolved/rejected and data has been successfully fetched. Any HTTP request takes much longer to complete than painting elements to the DOM. So your component loads with default data before being updated with the response from your API call a number of milliseconds later.
The way you've handled it with class-based components is fine. There are probably some optimizations you could add, but it should work as expected. You might even choose to render a Spinner component while you're fetching data from the API as well.
If you want a different approach using more modern React patterns, you can try and use the equivalent version with React hooks.
const Songs = ({ fetchSongs, songs, ...props }) => {
React.useEffect(() => {
// dispatch any redux actions upon mounting
// handle any component did update logic here as well
}, [songs])
// ...the rest of your component
}
Here are the docs for the useEffect hook.

How to update state of component in componentDidUpdate() without being stuck in an infinite re render?

I have a component with a componentDidMount() method that calls a method called getData() which gets the initial data and sets the initial state of the component.
class LogsSettings extends React.Component {
constructor(props) {
super(props);
this.settingsUrls = [
"/ui/settings/logging"
];
this.state = {
configSettings: {},
formSchema: formSchema
};
this.configSettings = {};
this.selected = "general";
}
getData = (url, selectedSetting) => {
fetch(url)
.then((response) => {
if (response.status !== 200) {
console.log('Looks like there was a problem. Status Code: ' +
response.status);
return;
}
response.json().then((response) => {
//pass formschema here
console.log(selectedSetting);
let newFormSchema = this.setNonDefaultValues(response.data, formSchema.subsections);
Object.assign(this.configSettings, response.data);
this.setState({
configSettings : this.configSettings,
formSchema: newFormSchema
});
});
}
)
.catch((err) => {
console.log('Fetch Error :-S', err);
});
};
componentDidMount() {
this.settingsUrls.map((settingUrl) => {
this.getData(settingUrl, this.selected)
})
}
componentDidUpdate() {
this.settingsUrls.map((settingUrl) => {
this.getData(settingUrl, this.props.selectedSetting)
})
}
render() {
return (
<div className="card-wrapper">
<h2>{formSchema.label.toUpperCase()}</h2>
{
formSchema.subsections.map((subSection) => {
return (
<>
<h3>{subSection['description']}</h3>
<div style={{marginBottom: '10px'}}></div>
{
subSection['input_fields'].map((inputField) => {
return buildForm(inputField, this.handleChange)
})
}
<hr></hr>
</>
)
})
}
<button className="button button-primary">Save Changes</button>
</div>
)
}
}
The selectedSetting parameter that gets passed to the getData() method in this component will change however and when this changes, I need to change the state of the component and get new data specific to the changed selectedSetting parameter.
The new selectedSetting is passed into the component as a prop. The problem is that I can't pass the new selectedSetting parameter to my getData method to update the state of the component as it gets caught in an infinite loop.
How do I go about passing the new selectedSetting to the getData() method without getting caught in an infinite loop? Is this even possible? If not, what is the best approach I should take?
note the selectedSetting parameter isn't used in the getData() function yet but will be and it will be used to get data from an API call and a new form schema which will then lead to the ConfigSettings and formSchema states being changed
If you look closely on the lifecycle of your component, after mount, you'll fetch then update the component. This will trigger the componentDidUpdate lifecycle method which will do the same thing, causing the infinite loop. You need to have a flag that checks whether this.props.selected changed. If it didn't, don't fetch the data else fetch as normal. In the update method, you have access to the previous props. (You may also do this in componentShouldUpdate method, but it'll be just outright risky)
componentDidUpdate(prevProps) {
if( prevProps.selectedSetting !== this.props.selectedSetting ){
this.settingsUrls.map((settingUrl) => {
this.getData(settingUrl, this.props.selectedSetting)
})
}
}
also just a heads up, I noticed that your didMount method, uses a default of "general" as the selected setting, since you want to be using this.props.selectedSetting might be better if it was the one being used instead and just set default props to "general".

React not re-rendering component after page refresh, even if the state changes

I've got really weird problem. I mean, to me, really. This is not some kind of "use setState instead of this.state" problem. I'm working on trip planning App. I'm using ContextAPI which provides login information and user data (logged user trips etc ) to the whole app.
"Schedule" component, showing day-by-day trip schedule is context subscriber.
Now I want to delete one of the trip days (Day, also subscribing to the context is component rendered by Schedule Component on the Schedule list). And then magic happens:
when I do it right after logging in to the app, everything is working fine. But when I'll refresh the page and delete another day, context state (which as I said, holds all the data, including Days on schedule list) changes (checked via developer tools) but Schedule component is not re-rendering itself, so deleted element remains visible.
But as I said, state changes, and everything is working fine without page refresh before deleting operation. Also when I switch to another tab (Schedule is just one of the tabs, I've got for example Costs and Notes tab on the navbar rendering Costs and Notes components), and then go back to the Schedule tab it re-renders and everything is looking fine, component is showing info accordingly to context state.
Code works like this: deletion (context function ) is triggered by delete icon click in Day.js (context subscriber), Day.js is rendered by Schedule.js (context subscriber too).
In Context.js
... context functions ...
//WRAPPER FOR DELETE FUNCTIONS
delete(url, deleteFunc) {
this.requestsApi.request(url, "DELETE", null)
.then(response => {
if(response.status===204) {
deleteFunc();
} else {
this.toggleRequestError(true);
}
})
.catch( err => {
console.log(err);
this.toggleRequestError(true);
});
}
deleteDay = (id, tripId) => {
let newTrip = this.state.userData.trips.find((trip => trip.id ===
tripId));
newTrip.days = newTrip.days.filter(day => day.id !== id)
this.updateTrip(newTrip);
}
updateTrip = (newTrip) => {
let trips = this.state.userData.trips;
this.setState(prevState => ({
userData : {
...prevState.userData,
trips: trips.map(trip => {
if(trip.id !== newTrip.id)
return trip;
else
return newTrip;
})
}
}
));
}
...
In Schedule.js
... in render's return ...
<ul>
{this.trip.days.map((day,index) => {
return <DayWithContext
inOverview={false}
key={index}
number={index}
day={day}
tripId={this.trip.id}
/>
})}
</ul>
....
In Day.js (delete icon)
...
<img
src={Delete}
alt="Delete icon"
className="mr-2"
style={this.icon}
onClick={() => {
this.props.context.delete(
`/days/${this.props.day.id}`,
() => this.props.context.deleteDay(this.props.day.id,
this.props.tripId)
);
}}
/>
...
Anyone is having any idea what's going on and why Schedule can be not re-rendered after deletion done after page refresh? And even if context state changes? Only idea I have for now is that this is some kind of a bug...
//UPDATE
In Schedule component, in function componentWillReceiveProps() I console log props.context.trip[0].day[0] - first day. It's not an object, just plain text, so its not evaluated "as I click on it in the console".
Before I delete it, console logs first item. After I delete it, console logs second item (so now it's first item on the list) so props given to Schedule are changing, but no render is triggered... What the hell is going on there?
//UPDATE 2
I've also noticed that when I switch to Schedule component from another component, it works good (for example I'm refreshing the page on /costs endpoint then click Schedule tab on navbar menu which leads to /schedule). But when I refresh the page when on /schedule endpoint, this "bug" occurs and component is not re-rendering.
//Render from Context:
...
render() {
const {
isLoggedIn,
wasLoginChecked,
userData,
isLogoutSuccesfulActive,
isLogoutUnSuccesfulActive,
isDataErrorActive,
isRequestErrorActive,
isDataLoaded
} = this.state;
const context = {
isLoggedIn,
wasLoginChecked,
isLogoutSuccesfulActive,
isLogoutUnSuccesfulActive,
isDataErrorActive,
isRequestErrorActive,
userData,
isDataLoaded,
requestsApi : this.requestsApi,
toggleLogin : this.toggleLogin,
checkLogin: this.checkLogin,
setUserData: this.setUserData,
loadData: this.loadData,
addTrip: this.addTrip,
delete: this.delete,
deleteDay: this.deleteDay,
deleteActivity: this.deleteActivity,
deleteTrip: this.deleteTrip,
updateTrip: this.updateTrip,
uncheckLogin: this.uncheckLogin,
toggleLogoutSuccesful: this.toggleLogoutSuccesful,
toggleLogoutUnSuccesful: this.toggleLogoutUnSuccesful,
toggleRequestError: this.toggleRequestError,
toggleDataError: this.toggleDataError
};
return (
<Context.Provider value={context}>
{this.props.children}
</Context.Provider>
)
}
}
export const Consumer = Context.Consumer;
-------------Context HOC:
export default function withContext(Component) {
return function ContextComponent(props) {
return (
<Context.Consumer>
{context => <Component {...props} context={context} />}
</Context.Consumer>
);
}
}
You mutate your state.
In this place, you change an object in the state without using setState:
newTrip.days = newTrip.days.filter(day => day.id !== id)
And then in your map function, you always return the same objects (it is already updated).
So, to fix your issue you can try to change your deleteDay method:
deleteDay = (id, tripId) => {
const trip = this.state.userData.trips.find((trip => trip.id ===
tripId));
const newTrip = {...trip, days: trip.days.filter(day => day.id !== id)};
this.updateTrip(newTrip);
}
UPDATE:
You have one more issue in your Schedule component.
You need to get current trip dynamically, don't set it in the constructor:
Try this:
constructor(props) {
super(props);
this.getTrip = this.getTrip.bind(this);
}
getTrip() {
return this.props.context.userData.trips.find(trip => {
return `${trip.id}`===this.props.match.params.id;
});
}
render() {
const trip = this.getTrip();
return (
...
<ul>
{trip.days.map((day,index) => {
return <DayWithContext
inOverview={false}
key={day.id}
number={index}
day={day}
tripId={trip.id}
/>
})}
</ul>
...
)
}

React component ignore displaying text for empty obj

I have a react component with a method that reads some data from an object and then returns the text on its status on another component.
The problem is that when the application is loading at first the obj length will be 0 initially and when the object data is loaded it will then
update and the obj.length will be higher than 0.
The what happens is this:
Scenario 1 (obj will actually have data)
-- App Loading
-- getTxt checks if obj is empty
-- As data is not loaded yet on the first call obj.length will return 0 so 'No Data Found' is displayed
-- Then when the app finishes loading it then updates and the obj.length > 0 so 'Found the data' is displayed
or
Scenario 2 (obj will be empty)
-- App Loading
-- getTxt checks if obj is empty
-- As data is not loaded yet on the first call obj.length will return 0 so 'No Data Found' is displayed
-- Then when the app finishes loading it then updates and the obj is actually empty so it can stay the same.
My problem is that if after the app is loaded and obj.length re-checked it returns > then 0 then I don't want to display the first 'No Data Found',
but I need to have the condition just in case after the app has finished loading the data the data is still = 0
Here is the code:
import React from 'react'
class MyComponent extends React.Component {
getTxt() {
if (this.props.obj.length > 0) {
return 'Found the data';
} else if (this.props.obj.length == 0) {
return 'No Data Found';
}
return 'Searching Data'
}
render() {
return <SomeComponent text={this.getTxt()}/>
}
}
export {MyComponent}
What can I do in order to get this done?
As stated in the comments by Felix Kling.
You have three different states.
Initial state
No data
There is some data
Initial state will have the data props set to null. After the data was received it could be an empty object {} or an object with some information.
I would probably write this in the following way:
class MyComponent extends React.Component {
getStatus() {
const { data } = this.props;
if (data === null) {
return "Searching data"
}
if (Object.keys(data).length === 0) {
return "No data was found"
}
return "Found some data"
}
render() {
return <SomeComponent text={this.getStaus()}/>
}
}
This is almost perfect because I would like to separate logic from the view. I will have a reducer that will get the data and upon its values/length it will determine the status.
const statusReducer = (data) => {
if (data === null) {
return "Searching data"
}
if (Object.keys(data).length === 0) {
return "No data was found"
}
return "Found some data"
}
class MyComponent extends React.Component {
state = { data: null }
componentDidMount() {
getData()
.then(resp => resp.json)
.then(resp => this.setState({data: resp.data})
}
render() {
return <SomeComponent text={statusReducer(this.state.data)} />
}
}
You may ask what's the point of passing this to another function (reducer)? First, as I mentioned, separating the logic from the view. Second, statusReducer can be reused in other components. Third, easier to test the code.
NOTE: We only took care of the happy path. However, if there was a problem with the request or the response contains error, we probably get the wrong status.
To handle such case lets look at a different approach. Lets have data and status in state
class MyComponent extends React.Component {
state = { data: null, status: 'PENDING' }
componentDidMount() {
getData()
.then(resp => resp.json)
.then(resp => this.setState({data: resp.data, status: 'COMPLETE'})
.catch(err => this.setState(data: err.Message, status: 'ERROR'})
}
render() {
switch(this.state.status) {
case 'COMPLETE':
return <SomeComponent text={statusReducer(this.state.data)} />
case 'ERROR':
return <ErrorComponent message={this.state.data} />
case 'PENDING':
return <Spinner />
default:
// there is a runtime/compiling error.
// Notify it in you console.log or something
return null // Here I am silently failing but that's not a good practice
}
}
}
We could do even better if we move the switch-case statement to another function and call it loadReducer. But I will let you decide whether to do it or not.
Please notice Eitan's solution too. He uses both componentDidMount and componentWillUpdate to update status.
It sounds like you don't want to render anything until the data is received?
What I do when I need to do this is use component state to keep track of loading status. When the component mounts, set state.loading to true.
componentDidMount() {
this.setState({loading: true})
}
Set loading to false once everything is updated.
componentDidUpdate() {
if (this.state.loading) {
this.setState({loading: false})
}
}
And in the render function, conditionally render based on loading state.
render() {
const text = this.state.loading ? "Loading..." : this.getTxt()
return <SomeComponent text={text}/>
}
I agree with Felix in the comments. You may be better off with a nested ternary in a functional component. The component should update whenever props to it obj are updated.
export const myComponent = (props) => {
return (
<SomeComponent
text={ props.obj ?
props.obj.length > 0 ?
'Found Data'
:
'No Data Found'
:
'Searching'
}
/>
)
}

How do I create an array after Axios response and Display it in React js

I am having trouble creating an array of titles from an Axios response. The method getTitles(props) receives data from the Axios response. How do I create an array of titles dynamically?
The functions I have tried in Javascript are for loops and EC6 mapping, nothing seems to work. Being new to react I could be missing something but I am not sure what it is.
React code
export default class Featured extends React.Component {
constructor() {
super();
this.state = {
data: null,
}
}
/**
* Received request from server
*/
componentDidMount(){
ApiCalls.articleData()
.then(function(data){
this.setState(function(){
return {
data: data
}
})
}.bind(this));
}
getTitles(props){
//-- What code do I place here?
console.log(props.data)
return ['test title', 'test title 2'];
}
/**
* Render request
*/
render() {
let dataResponse = JSON.stringify(this.state.data, null, 2);
const Articles = this.getTitles(this.state).map((title, i) => <Article key={i} title={title}/> );
return (
<div class="row">{Articles}
<pre>{dataResponse}</pre>
</div>
);
}
}
Axios Code
var ApiCalls = {
articleData: function(id){
return axios.all([getArticles(id)])
.then(function(arr){
return arr[0].data.data;
})
.catch(function (error) {
console.log(error);
})
},
React setState behaves asynchronously . Your articles get rendered before the ajax was called and was not re rendered due to asynchrony in setState.
This is what doc(https://reactjs.org/docs/react-component.html#setstate) says
setState() does not always immediately update the component. It may batch or defer the update until later. This makes reading this.state right after calling setState() a potential pitfall. Instead, use componentDidUpdate or a setState callback (setState(updater, callback)), either of which are guaranteed to fire after the update has been applied. If you need to set the state based on the previous state, read about the updater argument below.
You can render the article after successful ajax call like below
componentDidMount(){
ApiCalls.articleData()
.then(function(data){
render(<Article data={data}/>, document.getElementById('...'));
}.bind(this));
}
Because of the post above, I was able to fix the issue by the code example below To see a working example goto the git repo
ApiCalls.articleData()
.then(function(data){
const newData = data.map(c => {
return c.attributes.title;
})
const addElement = newData.map((title, i) => <ContentTiles key={i} title={title}/> );
const newState = Object.assign({}, this.state, {
newData: addElement
});
this.setState(newState);
}.bind(this));

Categories

Resources