0

I have a project that calls an API service on componentDidMount(), using the following code

class Posts extends Component {

    componentDidMount() {
        apiService.get(this.props.filters);
    }
}

const mapStateToProps = state => {
    return {
        filters: state.filters
    }
}

My component passes the filters from my redux store on to the API call.

But what if the filters change through another component? I can't seem to find the correct lifecycle method to re-call the api once that happens.

Miguel Stevens
  • 8,631
  • 18
  • 66
  • 125
  • 1
    do you use any type of redux middleware like redux-thunk or redux-saga? I believe it's easier to extend actions for such a case instead of making one component responsible of keeping storage up-to-date by monitoring its props – skyboyer Dec 17 '18 at 07:06
  • I am using sagas, but I'm new to it. Should I add a saga for the changedFilter action for example? And call the saga that calls the api? – Miguel Stevens Dec 17 '18 at 07:12
  • 1
    I have never worked with redux-saga but yes, I'm sure this logic should be there – skyboyer Dec 17 '18 at 07:21

2 Answers2

1

If you want to solve the problem locally you should use the componentDidUpdate method.

componentDidUpdate(oldProps, newProps) {
    if (this.notEqual(oldProps.filter, newProps.filter)) {
        apiService.get(this.props.filters);
    }
}

But I would consider lifting the data to Redux and sending an async action updating the api data from the filter change event handler.

Peter Ambruzs
  • 7,763
  • 3
  • 30
  • 36
  • Thanks for this, issue is that the change is a parameter of the object inside the filters array, so a shallow compare won't reveal the changes I think? – Miguel Stevens Dec 17 '18 at 07:14
  • You have to write a filter comparsioun function in this case, I updated the answer. Or you can lift the data to Redux. – Peter Ambruzs Dec 17 '18 at 07:19
  • 1
    @Notflip I'm not sure if components that relies on `store.filters` will be updated at all once you mutate data inside of `filters` instead of recreating new array with changed data. https://stackoverflow.com/a/40386189/2071697 – skyboyer Dec 17 '18 at 07:20
  • @skyboyer Aha so it might be a mutability mistake of me? I'll check, thanks! – Miguel Stevens Dec 17 '18 at 07:23
  • All the component with connect will be updated if the Redux state is changed. Unless your component extends PureComponent. If you extends PureComponent then componentWillUpdate is implemented with default shallow comparison on old and new props and only reRenders if this comparison detects changes. – Peter Ambruzs Dec 17 '18 at 07:31
  • @PeterAmbruzs Thats not correct. Only components whose props returned from mapStateToProps change will get re-rendered as Connect itself is a PureComponent – Shubham Khatri Dec 17 '18 at 07:35
  • Thanks for the info, I see my render method is getting called when I selected the new filter in the sidebar, I'm just wondering now where I should Call my api again? Since that api call expects 2 parameters.. – Miguel Stevens Dec 17 '18 at 07:47
  • @ShubhamKhatri there is some kind of comparison in the connect function, but it is not a simple shallow comparison. It is something deeper. It is new to me. Thanks. – Peter Ambruzs Dec 17 '18 at 12:25
0

Answer

Got it working using

componentDidUpdate(prevProps) {
    if(JSON.stringify(prevProps.filters) !== JSON.stringify(this.props.filters)) {
        // make API call
    }
}

Using JSON.stringify ensures that 2 empty arrays don't count as different.

Miguel Stevens
  • 8,631
  • 18
  • 66
  • 125