Why componentDidMount does not get fired? - javascript

I have a function which fires when the user clicks on it. The function calls setState, and the component rerenders itself. The only problem is that componentDidMount() does not get fired. Here's the code:
//the element which fires removeElem
<div onClick={this.removeElem}>
-
</div>
//the removeElem function gets called
removeElem = () => {
this.setState({status: 'deleted'})
}
//the component renders, the state has been changed
render(){
console.log(this.state.status) //the right value is logged after removeElem()
return(
//...
//componentDidMount
componentDidMount(){console.log("mounted")} //not logging
Why?

The componentDidMount() method just get trigerred when your component is mounted. You should use componentDidUpdate() method, that gets triggered when you update the state/props of your component.
You should read the React Docs for State and Lifecycle
See the snippet below:
class App extends React.Component {
state = { status: 'active' }
//componentDidMount
componentDidMount(){console.log("mounted")}
//componentDidUpdate
componentDidUpdate(){console.log("new status:",this.state.status)}
//the removeElem function gets called
removeElem = () => {
this.setState({status: 'deleted'})
}
//the component renders, the state has been changed
render(){
console.log(this.state.status) //the right value is logged
return( <button onClick={this.removeElem}>
Trigger it
</button>);
}
}
ReactDOM.render(<App/>,document.getElementById('root'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id='root'></div>

Related

State ReactJS and render method

I'm studying chapter State and lifecycle in reactJS with Clock class and I don't understand why I can re-render my variables "myFirstNumber, mySecondNumber, myWord" which are not states when I use this code in CodePen:
class Clock extends React.Component {
constructor(props) {
super(props);
this.state = {
date: new Date(),
};
this.mySecondNumber = 0;
}
componentDidMount() {
this.myFirstNumber = 0;
this.myWord = "Start";
this.timerID = setInterval(
() => this.tick(),
1000
);
}
componentWillUnmount() {
clearInterval(this.timerID);
}
tick() {
this.setState({
date: new Date(),
});
this.myFirstNumber += 1;
this.mySecondNumber += 1;
if (this.myFirstNumber ===5) {
this.myWord = "Finish";
}
}
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.state.date.toLocaleTimeString()}.</h2>
<h2>myFirstNumber from ComponentDidMount: {this.myFirstNumber}</h2>
<h2>mySecondNumber from constructor: {this.mySecondNumber}</h2>
<h2>myWord: {this.myWord}</h2>
</div>
);
}
}
ReactDOM.render(
<Clock />,
document.getElementById('root')
);
The render method render all DOM each seconde for my variables which are not states ?
When you call this.setState function, the DOM gets rerendered. Here the DOM is getting updated every second when this.state.date gets changed through this.setState, showing new values. However, if you keep date outside of state, you can see that the DOM no longer rerenders, same result if you want to change "myWord" or "firstNumber" without changing anything in state.
When you run tick() the setState part is what triggers the re-render and that will process everything, state or not.
In componentDidMount() you schedule interval which triggers tick() function every second. Inside this function you update component's state by invoking setState() and passing current time as a new state value. Moreover, you modify some local variables of the class. When arguments passed to setState() are processed by JS engine, what happens asynchronously, not immediately after setState() is called, the component updates its state.
Then the render() function is called by the framework. The render() function returns output which reflects the current values of all variables requested inside render() function. If you didn't call setState() inside tick() method then you wouldn't see any changes even though you modify myFirstNumber and other variables after each second.

react render called before componentdidmount

In my componentDidMount() I am making an API call "invokeservice" to fetch some data, this call then sets a state object that I use in my render.
The problem I am having is that the invokeservice is not being called and set the first time that the page is loaded, however when I refresh the page the invokeservice returns the data fine and the rest of the script will run. It's only the first time that it returns an null value.
Is it possible to call this invoke service in render function and keep the data ready and display it when user tries to load this page.
TRIED:
1.read that ComponentDidMount is called only after 1st initial render.
2. {this.invokeservice()} i tried to call in render function before return which did initial render but after 5sec it was blank and then again 5sec later it is filled again with values.
render function
public render() {
return (
<div className="monitor">
<div className="monitor__table">
{this.monitorrow(translate("cpu"), this.state.cpuString)}
{this.monitorrow(translate("memory"), this.state.pmemoryString)}
</div>
</div>
);
}
constructor
constructor(props) {
super(props);
this.state = {
cpu: 0,
cpuString: ""
};
setInterval(() => this.invokeservice(), 5000);
}
componentdidMount
public componentDidMount() {
this.invokeservice();
}
invokeservice
private invokeservice() {
var client = new HttpClient();
var url = this.props.baseUrl + '//getMonitorUsage' + '?NC=' + Date.now().toString();
client.get(url, (response) => {
this.setState({
cpu: JSONResponse.GetSystemStateResult.CPUusage
});
}
}
});
}
function
monitorrow(left,right) {
return (
<div className="table__row">
<div className="table__cell__left">
<Text>{left}</Text>
</div>
{ right &&
(<div className="table__cell__right">
<Text>{right}</Text>
</div>)
}
</div>
);
}
It is expected.
From the react docs:
These methods are called in the following order when an instance of a component is being created and inserted into the DOM:
constructor()
static getDerivedStateFromProps()
render()
componentDidMount()
Ref: https://reactjs.org/docs/react-component.html
There is componentWillMount which will be called before render(). But is it not advised to be used. Read more on the official docs https://reactjs.org/docs/react-component.html#unsafe_componentwillmount

returning component inside function not working

I've a component which i'm rendering by considering some conditions. It's done as follows
const Test = () => {
return <div className="text_align_center white_color">
<span><i className="fa fa-exclamation-triangle" aria-hidden="true"></i>
No internet connection. Please check your connection settings and try again
</span>
</div>
}
function checkInternetConnection(){
isOnline().then(online => {
if(online === true){
console.log("Came in here")
return <Test/>
}
});
}
Then i'm calling my function as follows
const App = () => (
<div className="ui container">
{checkInternetConnection()}
);
But the issue is eventhough i'm getting the console log inside checkInternetConnection function, the returned component is not appearing. What can be cause of this?
Your <Test/> is being returned by the then callback function, not your checkInternetConnection function. Because you are conditionally rendering based on some asynchronous operation, you need to take a different approach in order for your component to update correctly.
One idea is to turn your stateless component into a stateful component by making it a class, and calling setState when your promise resolves:
import React from 'react';
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
isOnline: false // set initial state to false
};
}
componentDidMount() {
isOnline().then(online => {
this.setState({
isOnline: true; // call setState to update state and rerender App
});
});
}
render() { // use inline expression to conditionally show <Test/> if isOnline is true
return (
<div className="ui container">
{ this.state.isOnline && <Test /> }
</div>
);
}
}
Since isOnline() has a .then() clause I assume it is an asynchronous Promise?
If that is the case, then that is your culprit. The component will not re-render when the promise returns as React only renders when state changes, which is not the case here.
To get the behavior you describe do the rendering of the Test component based on a state variable and set it in your .then() when the promise returns.

componentWillReceiveProps on react does not pass the current property when ever it triggers

Hello guys I'm new to react
I'm working with react component passing a property from a state of parent component and I'm not sure why i get an undefined property error whenever i trigger and event from the parent component
You can visit the code here# https://codepen.io/private_ryan/pen/RVBdpO?editors=0011#live-view show console and click the edit button
SampleTable Component
constructor(props, context) {
super(props);
this.state = { UPD:[] };
}
updateRow(x) {
var array = this.state.TRs;
var index = array.findIndex(e => e.id == x);
this.setState({
UPD: this.state.TRs[index]
});
}
render() {
return (<AddFormData onAdd={ this.onAddForm }
upd={ this.state.UPD }
updcan={ this.cancelUpd }
propUpd= { this.propcessUpd } />
<button onClick={ this.updateRow} value={ some.id } >click me</button>
);
}
AddFormData Component
constructor(props) {
super(props);
this.state = { textName: '', textArea: '' };
}
componentWillReceiveProps(){
console.log( this.props ) // undefined no props when first click
// set the state here
}
New props are received as parameters to the function:
componentWillReceiveProps(nextProps)
https://facebook.github.io/react/docs/react-component.html#componentwillreceiveprops
componentWillReceiveProps will get called whenever you do any changes in props values in parent component, new values will get passed as parameter and after this lifecycle method this.props will get updated so if you do console.log(this.props) inside this it will log the previous value not the new one.
Use this:
componentWillReceiveProps(newProps){
console.log(this.props.upd.id, newProps)
}
Check the working example.

React render method that depends on asynchronous request and state change

I am trying to learn ReactJS and Redux, and have come across a problem that I cannot seem to get over.
I have a React component, that gets data from an asynchronous request.
export class MyPage extends React.Component {
constructor(props) {
super(props)
this.state = {
enableFeature: false,
}
this.handleEnableFeatureChange = this.handleEnableFeatureChange.bind(this)
}
componentWillMount () {
this.fetchData()
}
fetchData () {
let token = this.props.token
this.props.actions.fetchData(token)
}
handleEnableFeatureChange (event) {
this.setState({ enableFeature: event.target.checked })
}
render () {
if (this.props.isFetching) {
return (
<div>Loading...</div>
)
} else {
return (
<div>
<label>Enable Feature
<input type="checkbox"
className="form-control"
checked={this.props.enableFeature}
onChange={this.handleEnableFeatureChange}
/>
</label>
</div>
)
}
}
}
So, my problem now is that, when I change the state of the checkbox, I want to update the state of my data. However, every time I update the state of my data, the react component method shouldComponentUpdate kicks in, and uses the current props to render the original data.
I would like to see how such cases are handled in general.
Thanks.
Try to do it like the following, i.e.
Use componentWillReceiveProps to assign props.enableFeature to state.enableFeature. From documentation
componentWillReceiveProps() is invoked before a mounted component receives new props. If you need to update the state in response to prop changes (for example, to reset it), you may compare this.props and nextProps and perform state transitions using this.setState() in this method.
Note that React may call this method even if the props have not changed, so make sure to compare the current and next values if you only want to handle changes. This may occur when the parent component causes your component to re-render.
componentWillReceiveProps() is not invoked if you just call this.setState()
Use this state to load the value of checkbox
Manipulate this state (onchange) to update the value of checkbox
Following code can work in your case
export class MyPage extends React.Component {
static propTypes = {
isFetching: React.PropTypes.bool,
enableFeature: React.PropTypes.bool,
token: React.PropTypes.string,
actions: React.PropTypes.shape({
fetchData: React.PropTypes.func
})
};
state = {
enableFeature: false,
};
componentWillMount () {
this.fetchData();
}
/* Assign received prop to state, so that this state can be used in render */
componentWillReceiveProps(nextProps) {
if (this.props.isFetching && !nextProps.isFetching) {
this.state.enableFeature = nextProps.enableFeature;
}
}
fetchData () {
const { token } = this.props;
this.props.actions.fetchData(token)
}
handleEnableFeatureChange = (event) => {
this.setState({ enableFeature: event.target.checked })
};
render () {
return (<div>
{ this.props.isFetching && "Loading..." }
{
!this.props.isFetching && <label>
Enable Feature
<input
type="checkbox"
className="form-control"
checked={this.state.enableFeature}
onChange={this.handleEnableFeatureChange}
/>
</label>
}
</div>);
}
}
Note: The above code was not executed, but should work (babel's stage-0 code)
Change it to checked={this.state.enableFeature}

Categories

Resources