Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Example of "Impure" Component

Tags:

reactjs

The React docs section on component specifications discusses keeping the render method "pure" and explains what that means.

I've run into a few situations where React throws an error because I am doing something improper in render, but would like to know if there are situations where a component could be "impure" but not trigger an error.

Could anyone provide an example of a component that does one or more of the following without throwing an error in React?

  • modifies component state in render (or anywhere else it shouldn't)
  • reads from or writes to the DOM when it shouldn't
  • doesn't return the same result each time it's invoked/rendered
  • (possibly the same as previous): doesn't render the same DOM for the same props and state
like image 409
cantera Avatar asked Dec 15 '14 21:12

cantera


People also ask

What are pure and impure components?

A Pure function is a function that does not modify any external variable. And the Impure function modifies the external variable. A basic principle of functional programming is that it avoids changing the application state and variables outside its scope.

What are pure and impure functions in React?

Pure functions are ones that do not attempt to change their inputs, and always return the same result for the same inputs. Example function sum(a, b) { return a + b; } Impure function is one that changes its own input. Example function withdraw(account, amount) { account.

What does pure component mean?

A React component is considered pure if it renders the same output for the same state and props. For this type of class component, React provides the PureComponent base class. Class components that extend the React. PureComponent class are treated as pure components.


1 Answers

Pretend these are all in render.

"modifies component state in render (or anywhere else it shouldn't)"

this.state.foo = whatever;

"reads from or writes to the DOM when it shouldn't"

if (this.isMounted()) { this.getDOMNode().textContent = whatever };
document.querySelector('title').textContent = whatever;

"doesn't return the same result each time it's invoked/rendered"

return <div>{Math.random()}</div>

"(possibly the same as previous): doesn't render the same DOM for the same props and state"

if (new Date().getHours()>=9 && new Date().getHours()<=12+5) {
    return <div>{this.props.fortune}</div>
}
else {
    return <div>I'm off the clock</div>
}

You mentioned the last example specifically in a comment, so the correct way to deal with time is to get the time in getInitialState, and then set a timeout in componentDidMount for when the time changing will affect rendering, and setState there. This way your UI stays in sync with the world.

A naive solution is to just setInterval to a few seconds, which is fine until you have time to optimize it. The real solution here would be something like

var now = Date.now(),
    closing = new Date(); closing.setHours(12+5, 0, 0, 0),
    opening = new Date(); opening.setHours(9, 0, 0, 0), delay; 

// past closing
if (now > closing || now < opening) {
    if (opening < now) {
        opening.setHours(9+24);
    }
    delay = opening - now;
}
// currently open
else {
    delay = closing - now;
}
setTimeout(delay, updateStateWithTime);

And like any state change over time, mixins are often a good way to abstract and reuse.

like image 180
Brigand Avatar answered Sep 21 '22 03:09

Brigand