romulof
romulof

Reputation: 367

Bind React Router query into component state

I'm trying to make a component that displays one option for the user to confirm or change to the previous/next option. This component is assigned for the route:

/choose?option=1

Where the query "option" is the displayed option, and clicking in "next" would change this query to "option=2".

To read the query and assign it to a state is pretty simple (using ES6+):

componentWillMount() {
  const { query } = this.props.location;
  this.setState({
    option: query.option ? Number.parseInt(query.option, 10) : 1,
  });
}

I also made a method to replace the location into the router, updating the URL without creating a new history state, which is the desired behavior:

setOption = (newOption) => {
  const newLocation = Object.assign(this.props.location, {
    query: {
      option: newOption,
    },
  });

  this.context.router.replace(newLocation);
};

The problem:

When I push this location into Router, it re-renders my component, and It's not a good idea to update state inside render method. I could drop using states for this and just use query params, but I don't like this option.

Is there a (elegant) way to bind these query parameters into component states?

Upvotes: 1

Views: 810

Answers (1)

romulof
romulof

Reputation: 367

Found one way do do it:

  componentWillMount() {
    // Triggered when component is created
    this.updateState(this.props);
  }

  componentWillReceiveProps(nextProps) {
    // Triggered when router updates location
    this.updateState(nextProps);
  }

  setOption = (newOption) => {
    const newLocation = Object.assign(this.props.location, {
      query: {
        option: newOption,
      },
    });

    this.context.router.replace(newLocation);
  };

  updateState = (props) => {
    const { query } = props.location;
    this.setState({
      option: query.option ? Number.parseInt(query.option, 10) : 1,
    });
  };

I'd appreciate suggestions :)

Upvotes: 1

Related Questions