LexShek
LexShek

Reputation: 13

My component doesn't rerender

When I click on button, I see '1' in console, but never see '2'. Why it happens? Can you help me please to resolve this issue? I realy dont know why my second component doesn't update.

class App extends PureComponent {
  constructor() {
    super();
    this.state = {
      name: 'Vasya'
    }
    this._onChange = this._onChange.bind(this);
  }

  _onChange(name) {
    this.setState({
      name: name
    });
  }
  
  render() {

    console.log(1);

    return {
      <div>
        <Button onClick={this._onChange('Petr')} />
        <AnotherComponent username={this.state.name} />
      </div>
    }
  }
}

class AnotherComponent extends PureComponent {
  const {
      username
    } = this.props
  
  render() {

    console.log(2);

    return {
      <div>
        test
      </div>
    }
  }
}

export default App;

Upvotes: 1

Views: 80

Answers (1)

Duncan Thacker
Duncan Thacker

Reputation: 5188

A few code problems in your example!

  • when you return your React elements from render(), they must be wrapped in parens () not curlies {}
  • use React.Component, not React.PureComponent, or you'll get issues
  • <Button> isn't a thing, use <button>

The main problem then is an infinite loop - when you render, this line:

<Button onClick={this._onChange('Petr')} />

...this calls the _onChange() function at render time and passes the result to Button as the onClick prop. This isn't what you want - you want the onClick prop to be a function that calls _onChange(). So

<button onClick={ () => this._onChange('Petr')} />

Full working example:

class App extends React.Component {
  constructor() {
    super();
    this.state = {
      name: 'Vasya'
    }
    this._onChange = this._onChange.bind(this);
  }

  _onChange(name) {
    this.setState({
      name: name
    });
  }
  
  render() {

    console.log(1);

    return (
      <div>
        <button onClick={ () => this._onChange("Petr") } />
        <AnotherComponent username={this.state.name} />
      </div>
    );
  }
}

class AnotherComponent extends React.Component {
  
  render() {

    console.log(2);

    return (
      <div>
        test
      </div>
    );
  }
}

ReactDOM.render(<App />, document.getElementById("app") );
<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="app"></div>

Upvotes: 1

Related Questions