chaitanya gupta
chaitanya gupta

Reputation: 352

How to call action and set state in componentDidUpdate() in react and redux (prevent infinte loop)

I have a navigation bar in my project which is common for all and it has a input text field

<input
    placeholder="Search Assets"
    type="text"
    id="searchTerm"
    onChange={this.searchAsset}
    value={this.state.searchValue}
/>

and function onChange i am redirecting to library page

searchAsset = event => {
    const searchValue = event.target.value;
    this.setState({ searchValue });
    if (searchValue.trim().length > 2) {
      this.props.history.push(`/company/library?q=${searchValue}`);
    }
  };

and in library page i am calling search action in componentDidMount()

componentDidMount() {
    const params = new URLSearchParams(this.props.location.search);
    const q = params.get('q');
    this.setState({ searchValue: q });
    this.props.actions.searchAssets({ page: 0, searchString: q });
  }

Now issue is whenever i am searching again - Suppose initially i searched "image" and after getting the result i deleted the text in top nav and again searched text "download" I am not getting any response from backend

Right now i want to achieve this issue with

componentDidUpdate(prevProp, prevState) {
    const params = new URLSearchParams(this.props.location.search);
    const q = params.get('q');
    if (q !== prevState.searchValue) {
      this.props.actions.searchAssets({ page: 0, searchString: q });
    }
  }

and i am getting the error Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate.

Upvotes: 1

Views: 368

Answers (1)

Drew Reese
Drew Reese

Reputation: 203373

Issue

Your componentDidUpdate version doesn't quite match the componentDidMount version. You always compare q to prevState.searchValue but don't update the state so the comparison is false on the next update. q !== prevState.searchValue never results in false and you appear to enqueue a bunch of actions that result in render looping.

Solution

Cache the current search result for the next state update comparison so the effect is run only when a new search query arrives.

componentDidUpdate(prevProp, prevState) {
  const params = new URLSearchParams(this.props.location.search);
  const q = params.get('q');
  if (q !== prevState.searchValue) {
    this.setState({ searchValue: q }); // <-- update state with search value
    this.props.actions.searchAssets({ page: 0, searchString: q });
  }
}

Upvotes: 2

Related Questions