BennKingy
BennKingy

Reputation: 1583

Updating the react state/component correctly?

I am trying to make my component reactive on updates. I am using componentDidUpdate() to check if the components prop state has changed, then if it has it is has I need the getPosts() function to be called and the postCount to update if that prop is changed.

export default class JsonFeed extends React.Component<IJsonFeedProps, IJsonFeedState> {

  // Props & state needed for the component
  constructor(props) {
    super(props);
    this.state = {
      description: this.props.description,
      posts: [],
      isLoading: true,
      jsonUrl: this.props.jsonUrl,
      postCount: this.props.postCount,
      errors: null,
      error: null
    };
  }

  // This function runs when a prop choice has been updated
  componentDidUpdate() {
    // Typical usage (don't forget to compare props):
    if (this.state !== this.state) {
      this.getPosts();
      // something else ????
    }
  }

  // This function runs when component is first renderd
  public componentDidMount() {
    this.getPosts();
  }

  // Grabs the posts from the json url
  public getPosts() {
    axios
      .get("https://cors-anywhere.herokuapp.com/" + this.props.jsonUrl)
      .then(response =>
        response.data.map(post => ({
          id: `${post.Id}`,
          name: `${post.Name}`,
          summary: `${post.Summary}`,
          url: `${post.AbsoluteUrl}`
        }))
      )
      .then(posts => {
        this.setState({
          posts,
          isLoading: false
        });
      })
    // We can still use the `.catch()` method since axios is promise-based
    .catch(error => this.setState({ error, isLoading: false }));
  }

Upvotes: 3

Views: 186

Answers (4)

Mohammed Al-Reai
Mohammed Al-Reai

Reputation: 2786

Try doing this

componentDidUpdate(prevState){
if(prevState.loading!==this.state.loading){
//do Something
    this.getPosts();

}}

Upvotes: 0

Kishan Jaiswal
Kishan Jaiswal

Reputation: 664

 // This function runs when a prop choice has been updated
   componentDidUpdate(prevProps,prevState) {
   // Typical usage (don't forget to compare props):
   if (prevState.jsonUrl !== this.state.jsonUrl) {
     this.getPosts();
     // something else ????
    }
   }

this way you have to match with the updated state

Upvotes: 1

Stavros Angelis
Stavros Angelis

Reputation: 962

You can change componentDidUpdate to:

componentDidUpdate() {
    if (this.state.loading) {
      this.getPosts();
    }
  }

This won't be an infinite loop as the getPosts() function sets state loading to false;

Now every time you need an update you just need to set your state loading to true.

If what you want to do is load everytime the jsonUrl updates then you need something like:

componentDidUpdate(prevProps) {
      if (prevProps.jsonUrl!== this.props.jsonUrl) {
         this.getPosts();
      }
}

Also I don't get why you expose your components state by making componentDidMount public.

Upvotes: 4

HMR
HMR

Reputation: 39250

Modify your getPosts to receive the jsonUrl argument and add the following function to your class:

static getDerivedStateFromProps(props, state) {
  if(props.jsonUrl!==state.jsonUrl){
    //pass jsonUrl to getPosts
    this.getPosts(props.jsonUrl);
    return {
      ...state,
      jsonUrl:props.jsonUrl
    }
  }
  return null;
}

You can get rid of the componentDidUpdate function.

You can also remove the getPosts from didmount if you don't set state jsonUrl in the constructor.

Upvotes: 2

Related Questions