0

I used to call AJAX after props change by ComponentWillReceiveProps()

componentWillReceiveProps(nextProps) {
    if(nextProps.foo !== this.props.foo){
       //fetch & call this.setState() asynchronously
    }
}

After React 16.3 ComponentWillReceiveProps() is going to be deprecated in the future. Instead of ComponentWillReceiveProps() there is a new function getDerivedStateFromProps, but I can't update state async.

static getDerivedStateFromProps(nextProps, prevState) {
    // I can't get access to this.props but only state

    if(nextProps.foo !== this.props.foo){
       //fetch & call this.setState() asynchronously
    }

    // I can only return a state but update it after an AJAX request
    return {}
}

What's the best practice to do it.

  • When you say you `can't update state async` will you please explain what you mean and show us the code you've tried? – larz Apr 13 '20 at 02:56
  • React intentionally deprecates `.componentWillReceiveProps()` to prevent misuse cases, and I suspect yours is one of those. You might want to describe your original intention, what are you trying to do here? Give us some context. – hackape Apr 13 '20 at 03:19
  • If your logic doesn't depends on `nextProps`, then you should use `componentDidUpdate()`. Even if it depends on `nextProps`, use `this.props` in that lifecycle instead is fine. – hackape Apr 13 '20 at 03:20
  • here's an update, some help pls – lmxx1234567 Apr 13 '20 at 03:39
  • If you need to perform a side effect (for example, data fetching AJAX call) in response to a change in props, use componentDidUpdate lifecycle instead.(https://reactjs.org/docs/react-component.html#static-getderivedstatefromprops [for more info]) – Dipesh KC Apr 13 '20 at 04:00

2 Answers2

2

The best place for do asynchronous calls is componentDidUpdate(prevProps, prevState, snapshot) {}. getDerivedStateFromProps is static method so it hasn’t access to component instance (hasn’t access to this)

Kirill Skomarovskiy
  • 1,535
  • 1
  • 7
  • 9
2

You should not use getDerivedStateFromProps lifecycle for making api calls. Instead, use componentDidUpdate to make api call and once you get the api response do this.setState. Also as pointed in another answer, you cannot use this in static method.

componentDidUpdate(prevProps) {
    if (this.props.myData !== prevProps.myData) {
      this.callMyApi();
    }
}

callMyApi() {
  fetch("/api")
    .then(response => {
      this.setState({ ... });
    })
}

If you are writing new component, you can also consider to write a Functional component and use useState and useEffect to trigger api call when a propis updated.

Like this:

...
  const {page} = this.props;
  const [images, setImages] = useState([]);

  useEffect(() => {
    fetch(`/myfavApi`)
      .then(data => data.json())
      .then(images => {
        setImages(images.concat(images));
      });
  }, [page]); // provide page(prop) as dependency. 
  ...
gdh
  • 13,114
  • 2
  • 16
  • 28