6

I've been learning new features of React 16.8. I believe React's Pure Component should automatically avoid unnecessary re-render operations.

In the following example, the App itself is a stateless component. I use useState to maintain two state objects text and nested: {text}.

There are 3 tests. The first 2 tests work. No matter how many times, I change the state, no re-render operation will be required.

Now, the third test tries to set the state of text with the same string value, but the reference is different. I expect nothing to be re-rendered, but actually, the <Headline/> will be re-rendered.

Shall I use certain memorize technique to avoid? I feel it will be too much code to archive that. And programmer must be very careful to write high-quality React code. ..

class Headline extends React.PureComponent {
  render() {
   const {text} = this.props;
   return <h1>{text} (render time: {Date.now()})</h1>;
  }
} 

const simpleText = 'hello world'

const App = () => {
  const [text, setText] = React.useState(simpleText)
  const [nested, setNested] = React.useState({text: simpleText})
  return (
    <div>
      <Headline text={text}/>
      <Headline text={nested.text}/>

      <button onClick={()=>setText(simpleText)}>
        test 1: the first line should not change (expected)
      </button>

      <button onClick={()=>setNested({text: simpleText})}>
        test 2: the second line will not change  (expected)
      </button>

      <button onClick={()=>setText(new String(simpleText))}>
        test 3: the first line will change on every click (why?)
      </button>
    </div>
  )
}

ReactDOM.render(<App />, document.querySelector("#app"))

Here is a live playground in jsfiddle:

https://jsfiddle.net/fL0psxwo/1/

Thank you React folks, cheers!


Update 1: Thanks Dennis for mentioning why-did-you-render

The author points some very useful articles. I think it could be very educational to everybody. https://medium.com/welldone-software/why-did-you-render-mr-big-pure-react-component-part-2-common-fixing-scenarios-667bfdec2e0f

Update 2: I created a new hook called withDirtyCheck so that my code will automatically do content dirty check.

import isEqual from 'lodash-es/isEqual';

export const withDirtyCheck = ([getter, setter]) => {
  const setStateIfDirty = (nextState) =>
    setter((prevState) => (isEqual(prevState, nextState) ? prevState : nextState));

  return [getter, setStateIfDirty];
};

Checkout my latest library https://github.com/stanleyxu2005/react-einfach

2
  • Where does PureComponent enter into this? Your examples don't include it. Commented Jul 17, 2019 at 14:50
  • I need to revise my question. I mean stateless functional component. I thought it equals pure class component. (my bad) Commented Jul 17, 2019 at 14:54

1 Answer 1

3

The problem is that with new operator you creating a String Object which is always different from the previous state.

'hello world' === new String('hello world') // false, always.
'hello world' === String('hello world')     // true

Check this example:

setText(prevState => {

  // Will render
  // const currState = new String(simpleText);

  // Won't render
  const currState = String(simpleText);

  console.log(prevState === currState); // if true, no re-render
                                        // if false, re-render

  return currState;
});

Edit antd-starter

Refer to What is the difference between string primitives and String objects in JavaScript?

Sign up to request clarification or add additional context in comments.

3 Comments

I take your point. I think my major wrong is that, I consider stateless component is same as pure component. But they actually behave quite differently.
But you know, in a large project, some people (like me) can be wrong to write shitty code. My wish is even if I write something like new String(...), I can still find the problem at static-checking stage, or use some built-in/3rd-party content level dirty checks to help.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.