M
M
max1072015-11-24 12:23:46
Software design
max107, 2015-11-24 12:23:46

React + Redux. Proper use of QueryString and componentWillReceiveProps?

Dear Colleagues, Need help with redux "recursiveness" issue.
Description of the problem:
The essence is that the component receives propsfrom react-routerand componentWillMountloads the first page of records. Everything is great at this stage.
Next, we filter / sort the data or use pagination and send the user to a new url with a changed qs (example /news/list?page=2). At this stage, logically, you need to use componentWillReceiveProps, since the component has remained the same, but new data has arrived. If we execute inside this method dispatch(actions.чтонибудь()), then we will receive data in props and here recursion occurs.

react-router -> componentWillReceiveProps -> dispatch -> componentWillReceiveProps -> dispatch -> ...

Question:
How do you use redux in these situations and how to avoid this problem?
Additional information:
Since perhaps I did not quite correctly express my thoughts, I will try to paraphrase. The componentWillReceiveProps receives props passed from source N, as well as a new state received from redux. In the end, the state of the component itself is not involved at all, but props is a mess.
Immutable.js can be used to avoid recursion when redux dispatch calls itself, but this doesn't seem like a solution to the problem to me since 1) You have to store an extra key-value in state 2) Reset values ​​at some point. And of course you will have to follow this manually.
Another option that seems to me also not quite adequate is to check everything by hand:
const { params } = nextProps;
if (params.page != this.props.page || params.page_size != this.props.page_size || params.order != this.props.order || ...) {

The option is not an adequate solution for complex projects or difficult conditions where the parameters involved in the check can be N, or they can be dynamic at all.

Answer the question

In order to leave comments, you need to log in

1 answer(s)
N
Nikita Gushchin, 2015-11-24
@max107

In this situation, the component should be connected to redux via connect. Then you will have the opportunity to see what is already loaded and what is not.
If you have some complex logic - I would suggest making an isLoaded flag and passing it as props to the component. Then, in the componentWillReceiveProps method, you can check if this flag is clear by calling the load function.
But specifically in this case, it's better to do what was done in the official real-world-example example : check if the page number has changed and only in this case dispatch the actions.
UPD1. Code example:

// MyComponent
import shallowequal from 'shallowequal';

export default class MyComponent {
  static propTypes = {
    items: PropTypes.array.isRequired,
    filtres: PropTypes.object.isRequired, // <-- тут можно собрать все фильтры
  };

  componentWillReceiveProps(nextProps) {
    if(!shallowequal(this.props.filtres, nextProps.filtres)) {
        loadData(filtres);
    };
  }
}

// MyComponentContainer
import MyComponent from './MyComponent';

function mapState(state, ownProps) {
  return {
    items: applyFiltres(state.someReducer.someItems),
    filtres: ownProps.location.query, // <--- как пример
  };
}

export default connect(mapState)(MyComponent);

In this case, our component (MyComponent) is independent of the router and redax. At the same time, the componentWillReceiveProps method is quite simple.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question