0

I'm trying to click on a div that has the onClick function associated with it, but the function doesnt getting called due to the fact that I have a setState inside a setInterval called every 0.1 sec. This updates the DOM and doesnt let me call the function onClick.

I tried to use PureComponent and React.memo to avoid re-renders nested Components, but it didn't work; I could not use them properly though.

Inside the father constructor I have, basically, this:

setInterval(()=> { 
    this.setState({state1: 0})
    }, 100)
}

EDIT

I'm proud of showing you the minimum (almost) code to test the issue (note the functional component: if you remove it and replace the < F /> with its content, it will work properly. Also, if you debug with google chrome, you will see what's going on the DOM):

 class App extends Component {
      constructor() {
        super()
        this.state = {state1: 0}
        setInterval(() => {this.setState({state1: this.state.state1 + 1})}, 100)
      }

      render() {
        const F = () => (
          <button onClick={()=> alert("this function will be called... sometimes")}> 
              test: {this.state.state1}
          </button>
        )
        return <div> <F/> </div>
      }
    }

EDIT 2

If I write the functional component as a pure function, it will work. here's the example:

class App extends Component {
  constructor() {
    super()
    this.state = { state1: 0}
    setInterval(() => {this.setState({state1: this.state.state1 + 1})}, 100)
  }

  render() {
    const F = ({state1}) => (
      <button onClick={()=> {alert("called sometimes")}}> test (will be called sometimes): {state1} </button>
    )

    function f(state1) {
      return <button onClick={()=> {alert("called always")}}> test(will be called always): {state1} </button>
    }

    return <div> <F state1={this.state.state1}/> {f(this.state.state1)}</div>
  }
}
E. C.
  • 1
  • 2

2 Answers2

0

setState will, by default rerender components that are impacted by said state.

This was answered here.

I would suggest moving away from setting state that often. That's quite expensive and I'm betting there is a far more efficient way to accomplish whatever it is that you're trying to do without the interval.

technicallynick
  • 1,562
  • 8
  • 15
  • There are some good alternatives to execute multiple setState without using setInterval? Btw I tried shouldComponentUpdate but it didnt work neither – E. C. Aug 14 '19 at 20:24
0

If you are using React 16.8^ then you could use Hooks to make multiple state changes. Note that instead of using setInterval i used setTimeout for each cycle

import React, {useState, useEffect} from 'react';

const App = (props) => {
    const [numberShown, setNumberShown] = useState(0);

    useEffect(() => {
        setTimeout(() => setNumberShown(numberShown + 1), 100);
    }, [numberShown]);

    return (<div>
       {numberShown}
    </div>)
}

Hope it helps

EDIT : I found a way to do it the Component Way:

class App extends Component {
    constructor() {
        super()
        this.state = {state1: 0}
        this.startTimer = this.startTimer.bind(this)
        this.startTimer()
    }
    startTimer = () => {
        setInterval(() => {this.setState({state1: this.state.state1 + 1})}, 100)
    }
    render() {
        return <button onClick={()=> alert("this function will be called... sometimes")}>
            test: {this.state.state1}
        </button>
    }
}

By experimenting i noticed that if you render the button like this:

  render() {
    const F = () => (
      <button onClick={()=> alert("this function will be called... sometimes")}> 
          test: {this.state.state1}
      </button>
    )
    return <div> <F/> </div>
  }

Instead of directly returning the button tag, the nested onClick function triggering the alert won't always go off but if you do it like in my example it will always trigger.

Japsz
  • 785
  • 6
  • 14
  • Thanks for your reply! I state that i dont know how it works exactly with Hooks, but if I add a functional component on render method, I have the same problem – E. C. Aug 14 '19 at 21:15
  • Changed some thing in case you missed it. Let me know if it works for you – Japsz Aug 14 '19 at 22:28
  • Yes, I checked it; the problem here is that it works without the intermedial functional component (I wrote the "note the functional component" concept on Edit part), the challenge should be to find a way to work with it. I found a way to do this and i'm preparing to write an "Edit 2" part – E. C. Aug 15 '19 at 09:00