tomashauser
tomashauser

Reputation: 571

How to update state of a parent while using its another state without causing infinite updates?

Let's have components A and B.

Component B only shows the parent's state in contentForB in a different format and doesn't manipulate with it. It takes A's state as a prop, applies a function transform(content) and shows it, so whenever A's contentForB changes, the new content get transformed and updated in B.

The problem comes when A wants to use B's transformed content and use it somewhere else. I tried to implemented in a standard way, using state-updating function and passed it from A to B like this:

class A extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            contentForB: "",
            transformedContent: ""
        };
        this.updateTransformedContent = this.updateTransformedContent.bind(this);
    }
    
    updateTransformedContent(newContent) {
        this.setState = { transformedContent: newContent };
    }

    render() {
        return (
            ...
            <B content={ this.state.contentForB }
               updateTransformedContent={ this.updateTransformedContent } />
            <ComponentUsingTransformedContent transformedContent = { this.state.transformedContent } />
        );
    }
}

class B extends React.Component {
    constructor(props) {
        super(props);
        this.transform = this.transform.bind(this);
    }
    
    transform(content) {
       let newContent = ...;     ​
       ​this.props.updateTransformedContent(newContent);
       ​return newContent;
   ​}

   ​render() {
       ​<Something value={this.transform(this.props.content)} />
   ​}
}

However, when A's state changes, B gets reinitialized, it then changes A's state by calling the updateTransformedContent which again causes B to get reinitialized, thus causing an infinite loop even though the updateTransformedContent changes the state object which isn't directly passed into B.

Any ideas how to deal with such situation properly?

Upvotes: 1

Views: 55

Answers (1)

Eric Thomas
Eric Thomas

Reputation: 149

You can use componentDidUpdate lifecycle method.

[codesandbox.io] https://codesandbox.io/s/cool-leaf-92nt8?file=/src/App.js:457-475

class TestB extends Component {
  constructor(props) {
    super(props);
    this.state = {
      transformed: ""
    };
    this.transform = this.transform.bind(this);
  }

  componentDidUpdate(prevProps) {
    if (this.props.content !== prevProps.content) {
      this.transform(this.props.content);
    }
  }

  transform(content) {
    const transformed = `<h4>${this.props.content}</h4>`;
    this.setState({ transformed: transformed });
    this.props.updateTransformedContent(transformed);
    return transformed;
  }

  render() {
    return (
      <div>
        <h4>B Componenet:</h4>
        <p>{this.state.transformed}</p>
      </div>
    );
  }
}

Upvotes: 1

Related Questions