I set up a new react project and for some reason, the componentDidMount method is not being called.
I have verified this behavior by placing a call to console.log in componentDidMount but I cannot see its output in the console.
Furthermore, this.setState() is not working.
I'm pretty stumped as to why the componentDidMount is not being called. I tried using both React "v0.14.0" and "v0.14.3".
Why is 'componentDidMount' not being called?
Code:
var React = require('react');
var RecipePage = React.createClass({
componentDidMount: function() {
console.log('mounted!');
},
render: function() {
return (
<div>Random Page</div>
);
}
});
module.exports = RecipePage;
This happened to me when I had componentWillMount() defined 2x in the same class. This did not produce a runtime error. I simply removed the second definition and things started working.
So... lo and behold.... I finally got it working(with the help of a back-end expert). The reason why the "componentDidMount" methods weren't firing was because my server was bundling and serving all the react + html stuff on server side. (Only "render" and "getInitialState" methods get called to create the "html" template that gets delivered through the client's browser...but it stops there because it thinks it's finished)
The fix: Find a way to deliver the resulting "compiled" html through the server AND in addition, allow react's own events to be accessible and "fireable" again on the client side. When compiling my "view" file( index.js or index.html ), I included an "Application.start()" script that injects my bundle.js code into the template again. Then in my gulpfile, exported the "Application" variable so the "view" file can access it.
Gahh...pulled my hair out for this. Time to read up on server side vs. client side rendering
In my case, there was another componentDidMount earlier in the code
I have the create-react-app template. I added the ComponentDidMount into the App Component. I put a console.log and an alert into it. It does not fire and there are no errors in React or the browser. I tried in chrome and firefox.
FIX: what worked for me was rebooting my pc. Then it started working. I do not know why, but this resolve the issue.
Update: Not I have an uppercase 'C' it is 'componentDidMount' not 'ComponentDidMount'.. I think it's time for sleep.
In my case, I call componentDidMount() for retrieving data from a service (API call) and on the render function I have components that are supposed to use the data that is returned from this call.
But because the call is Async the render() function is called immediately and then it crashes (many errors like: "TypeError:cannot read property 'XXXX' of undefined" ) then it looks like componentDidMount is not called at all.
To solve this issue I check on render that myData !== null before returning the component itself - You can use generic loader\spinner on this case that will not render internal components that use data before the data that actually retrieve from service.
Example:
componentDidMount() {
const { GetMyDataFromServiceFunc } = this.props;
GetMyDataFromServiceFunc ("150288");
}
render() {
const { details, loading } = this.props;
if (!details)
return (<GenericLoader />);
return (
<FullScreenModal
<Wizard className="order-new-wizard">
<Component1 editable={false} dataToComponent1={details}
goNextStep={this.goNextStep} />
<Component2 values={details.customerDetail} goNextStep={this.goNextStep} />
</Wizard>
</FullScreenModal>
);
}
}
You need to change your module.exports to point at RecipePage not TestPage
module.exports = RecipePage;
For me, the reason was upper case "C" in ComponentDidMount.
Changed it to componentDidMount and it worked
For me I also declared componentDidUpdate in the class after that componentDidMount started firing as expected.
Although you have a console log statement in your componentDidMount function it may not be executing because that function never gets run. If the error occurs before componentDidMount gets called such as in your render function, you won't see the console log. Try commenting out the code in your render function and see if it appears.
In my case, I imported a component without the export default command in the imported file. When I fixed this, componentDidMount started firing...
For me, I had onComponentDidMount() instead of componentDidMount() facepalm
componentDidMount did not fire for me because I mistakenly called it twice. Also, it will not show any console error. Removing one of them worked perfectly.
Related
I want to add a Listener beforeRemove to a navigation to prevent the user from going back.
Then they get an alert to proceed or discard.
I followed the tutorial from reactnaviagtion.org but this is in an functional Component.
In my Case its an react-native Class-Component.
I can easily call the function over the props:
componentDidMount(){
this.props.navigation.addListener("beforeRemove", (e) =>{
console.log("beforeRemoveTriggered");
this.state.SomeVariablesToCheckIfGameStarted
Alert.alert(..., onPress: ()=> this.props.navigation.dispatch(e.data.action));
}
}
The console.log is no problem but I can't call the state inside of the callback.
beforeRemoveTriggered
But after that I get the following error:
TypeError: undefined is not an object (evaluating '_this2.props.someVariablesToCheckIfGameStarted`)
- node_modules\...
My Guess is that you cant call the state inside of the listener-callback.
But this is neccessary for the app function so i cant "just dont use the state".
BTW a workaround with useEffect would be accetable but is not preferred.
This may have a simple solution which is not specific with react-navigation or react-native but javascript.
Any tips would be helpful, thanks in advance!!!
I know my answer...
Maybe but just maybe I called this.props instead of this.state
And maybe after this discovery everything works as it should be...
I`m sorry to everyone I bothered figuring out what the solution is!
I have been able to find limited information on this error and was hoping someone could take a deep dive into explaining exactly what causes this. I haven't changed any of the code that appears to be showing up in the call stack recently, so I was wondering if this is from a newer update?
In my case, The error/warning was casued by the react-block-ui package. Currently there is an opened issue at github of that package. The issue hasn't been solved so far.
It's a react issue. You can check if any third-party-packages are causing this. You can check this to see exactly where the error is coming from. I found these comments from there -
// We're already rendering, so we can't synchronously flush pending work.
// This is probably a nested event dispatch triggered by a lifecycle/effect,
// like `el.focus()`. Exit.
I hope this helps.
My problem was putting the debugger inside the code. As soon as I removed it, the error went away. So just in case
I spent quite some time debugging a similar issue on my project. In the end, we were calling focus inside a setState function, but this can be quite hidden by callbacks. In our case this was looking at this:
class ChildComponent extends React.Component {
func() {
this.setState(state => {
// ... Doing something
this.props.onStateChange();
// ... Returning some state
});
}
}
And then elsewhere:
onStateChange = () => {
this.element.focus();
};
render() {
return <ChildComponent onStateChange={this.onStateChange} />;
}
I solved the problem by calling the callback in componentDidUpdate:
class ChildComponent extends React.Component {
func() {
this.setState(state => {
// ... Doing something
// ... Returning some state
});
}
componentDidUpdate(prevProps, prevState) {
if (compare(prevState, this.state)) {
this.props.onStateChange();
}
}
}
Another possible solution: A colleague of mine also suggested to use requestAnimationFrame inside setState so that the call would be happening out of the render cycle.
Hope this will help some people coming here!
The Problem
I have an application that uses this React Redux Boilerplate: https://github.com/flexdinesh/react-redux-boilerplate
I created a new page that is connected to the injected reducer + saga.
I receive following props: posts, loading, error, loadPosts and match
When I use these directly the app is working as expected. But as soon as I start to destructure the props, the app is behaving unexpectedly.
Especially with the match props.
When I do it like this:
const SubforumPage = (props) => {
useEffect(() => {
const { id: subId } = props.match.params;
console.log('props: ', subId);
}, []);
// .... other code
}
No problem everything works.
But when I do it like this:
const SubforumPage = ({match}) => {
useEffect(() => {
const { id: subId } = match.params;
console.log('props: ', subId);
}, []);
// .... other code
}
match suddenly gets undefined!
I have really no clue what so ever why this is happening. It's the first time that I see an error like this.
This specific page is set up like this in the routing file:
<Route path="/sub/:id" component={SubforumPage} />
And it's clearly working when using (props) in the function arguments but not with ({match})
Why is this? Can please someone help me out here.
What have I tried?
I continuesly started destructuring one prop after another. At first this approach works and it's still not undefined but when I get to some props, it's different which ones, it will stop working.
I think it has to do something with how I use my useEffect() hook?
I pass an empty array so it does just run when mounting. It seems like when I refresh the page, the posts are cleared out but the useEffect doesn't run anymore, so the new posts doesn't get fetched. Because hen also the console.log inside the useEffect hook is undefined doesn't even run. But for example the loading prop in console.log outside of useEffect is indeed not undefined
(But that still does not explain why it's working with (props) as argument).
Am I just using useEffect wrong?
Many thanks
Ok guys that was completely my fault. Guess I'm too tired :D. Here is what caused the problem:
I fetch my post in the useEffect hook. I also render a component where I pass in the posts. But the posts are not available because the component has to wait for the data to come in. So I completely forgot that I have to wait for the data.
Before:
return <PostsGroup posts={posts} />;
After: (correct)
return <PostsGroup posts={posts || []} />;
I had a check in place looking like this:
if (loading) return <CircularProgress />;
(before the other return). But it doesn't matter because loading is false when the component initially renders.
So I also set the initial value from loading to true (in my initialState of the reducer). So I have now two checks in place.
Sorry guys. So stupid.
I have been working with Redux & React for a few months. I usually always use Chrome with no issues. ( Endless bugs actually :) ).
When I started testing in Firefox I ran into an issue which I need some help with ... To know if there is a perfect way at dealing with this ...
Issue
Redux Props for MapStateToProps are not yet available when the constructor gets called, which means I cannot construct my components state in the component constructor. These props become available swiftly afterwards in the render function. At this stage, it is too late because I cannot construct state in the render function (Could somehow work that, but wouldn't be good to approach right ?).
For the moment I am using the componentWillReceiveProps and duplicating my constructor function with one exception
Constructor function
constructor(props){
super(props);
//Loads of code named A
this.state = {state:A};
}
Component Will Receive Props Function
componentWillReceiveProps (){
//Loads of code named A
this.setState({state:A});
}
There may be an issue over overwriting my state here, but for my exact case here, its only displaying data, no UI changes happen... This doesn't appear correct method either way...
I read this article
https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html
I am not quite sure if I understand this fully. I did experiment with it a little with no working solutions.
Ideally, I need the constructor to pause until all redux store is populated which also doesn't make sense. Props arrays could be empty.
There are discussions on Slack but none seem to address this exactly. I tried googling issue but couldn't find exact issue addressed ...
I need the mapStateToProps props to construct my state. It is looking like I won't be able to do this and will need to totally refactor code to work more solely in the render function with loads of ternary operators and/or making calls to set state from the render function before the render returns.
Any thoughts on this issue?
Daniel
Why do you think you need put the data you get from props into the component state?
As far as using the data there is no difference between the two except that you're more likely to get into trouble if you copy props to state (see link you posted).
const { A } = this.state;
const { A } = this.props;
If the data is coming via an async method then you should accommodate that in your render method.
render() {
const { A } = this.props;
if (!A) {
return <LoadingIndicator />
}
...
}
I am working on a project using React Router, and I'm having some problems with the data flow.
On every page there is an AJAX call that gets the data for the component. I have been putting them in componentDidMount:
// Below code is written in ES6
componentDidMount(){
$.get(someURL, (data)=>{
this.setState({data:data})
})
}
Although this works on initial load, it does not get called again when the url changes (a manual refresh is needed). I cannot seem to find a proper life cycle to place the AJAX calls.
Someone please enlighten me with the proper approach to getting data in React Router.
After a bit of searching around, this README ultimately solves the problem.
There are 2 solutions outlined in the document:
Use addHandlerKey={true}:
<Route handler={User} path="/user/:userId" addHandlerKey={true} />
Use componentWillReceiveProps instead of componentDidMount.
I ended up using both, componentDidMount for the initial load, componentWillReceiveProps for subsequent ones.
Since they share the same code, I created a new function _updateState and called it in both lifecycles.
My code now:
class Classes extends React.Component {
componentDidMount(){ this._updateState() }
componentWillReceiveProps(){ this._updateState() }
_updateState(){
$.get(/*Some URL*/, (data)=>{
this.setState({data:data})
})
}
}