Reputation: 2319
I've seen many posts regarding this.props
, but none of them seems to answer my question, or at least I couldn't find it.
My component uses this.props
as args to get my url
This following code is almost the exact copy of https://reactjs.org/docs/faq-ajax.html
import React, { Component } from 'react';
class MyList extends Component {
constructor(props) {
super(props);
this.state = {
error: null,
isLoaded: false,
items: []
};
}
componentDidMount() {
let entityKey = this.props.eKey;
fetch(`some/url/${this.props.eKey}`)
.then(res => res.json())
.then(
(result) => {
this.setState({
isLoaded: true,
items: result
});
},
(error) => {
this.setState({
isLoaded: true,
error
});
}
)
}
render() {
const { error, isLoaded, items } = this.state;
if (error) {
return <div>Error: {error.message}</div>;
} else if (!isLoaded) {
return <div>Loading My List...</div>;
} else {
if (!items) {
return <div>Failed to Load My List</div>;
} else {
return (
<ul>
{items.map(item => (
<li key={item}>
{item}
</li>
))}
</ul>
);
}
}
}
}
export default MyList
Now my script that calls this is simply
class MyFunc extends Component {
return (
<div>
<MyList
eKey={this.props.eKey}
/>
</dev>
);
}
I eliminated other code in MyFunc
for simplicity
When I console.log
my this.props
inside MyList
, it returns {eKey: ""}
, so I know that the eKey
is being passed in. However, as you can see, it's empty.
I don't know if it's because I have this at the componentDidMount
cycle which for some reason this.props
hasn't arrived when fetch
ing. If that's the case, how do I guarantee the arrival before executing that line?
If it's somewhere else where I have issue, what went wrong?
EDIT:
To add in some more info. This is tied to a reducer. The redux is not exactly my strong suite.....so please correct me on any concept that's wrong.
The reducer takes the initialState
and an action
. The action can be different things. The only place that eKey
is loaded is when action.type='load'
export function reducer(state = initialState, action) {
switch (action.type) {
case LOAD:
return {
...state,
eKey: action.data.eKey,
// and some other stuff
};
// some other cases here
default:
return state;
}
}
Interesting thing is there's a submit button that updates another component, which supposedly get a new eKey
and get the eKey's data. At that time, the eKey is always populated, but my myList
is not updated accordingly. I think it's another issue I have to figure out, but just wanna put it out here in case it's somehow related.
It seems like the reducer is not called only the component is mounted and componentDidMount
is already called. And MyList
does not update when the reducer is finally called. I'm not sure how to solve this problem
EDIT 2:
I tried moving what's inside componentDidMount
into the render
function (with some mod, of course). Does it work? sure, but when I console.log
something, it just continues to print out stuff. Seems like this render function is constantly receiving update. I'm not sure if this is normal as my reactjs knowledge is not enough to answer this question. It works, but I'm wondering if this is the right way to do things
Upvotes: 2
Views: 2027
Reputation: 2319
I solved my problem by calling another function, so my code looks like
class MyList extends Component {
constructor(props) {
super(props);
this.state = {
error: null,
isLoaded: false,
items: []
};
}
componentDidMount() {
this.props.loadMystuff().then(() => {
if (this.state.eKey !== this.props.eKey) {
let eKey = this.props.eKey;
this.fetchSList(eKey);
}
}).catch((error) => toast(error.message));
}
fetchSList(eKey) {
if (eKey !== '') {
fetch(`some_api_url_config/${this.props.entityKey}`)
.then(res => res.json())
.then(
(result) => {
this.setState({
isLoaded: true,
items: result
});
},
(error) => {
this.setState({
isLoaded: true,
error
});
}
);
}
}
render() {
const { error, isLoaded, items } = this.state;
if (items) {
return (
<div>
<h3>S List</h3>
<ul>
{items.map(item => (
<li key={item}>
{item}
</li>
))}
</ul>
</div>
);
} else if (error) {
return <div>Error: List Missing...{error.message}</div>;
} else if (!isLoaded) {
return <div>Loading List...</div>;
} else {
return <div>Not Found</div>;
}
}
}
Note that the loadMyStuff
is the one retrieving the eKey, so calling that will effectively get me the eKey to resolve the timing issue
Upvotes: 1