2

I'm trying to create filters in react, where i manipulate the url to return me products based on colours, cost etc

its working so if you change ?color=red to ?color=white in the url it will display different products on the page

it's also working whereby if you select the colours in my checkbox filter component it will update the url and then display the new products. i.e click on red will change the url from /sport to /sport?color=red and then returns me just the products with red

however this is my problem

if I manually change the url, I then want the checkbox checked so I tried to do this:

checked={option.text === this.getParams() ? true : false}

this does actually work but then I lose the ability to actually select and deselect the checkbox. any ideas how I can get it to do both? I guess making it a controlled and uncontrolled component simultaneously??

2
  • Is the change in the url, refreshing the page? you could try the defaultChecked property. Commented Jun 21, 2018 at 8:06
  • its hard to give an answer with the amount of information you gave. which checkbox are you wanting to check when the url is typed in? is this a single page application? what does the function this.getParams() return? can you setup a codepen describing the issue? Commented Jun 21, 2018 at 8:14

2 Answers 2

1

You need to store the filters in the state. like in your constructor you can init your state with the query parameter and then change the state upon checkbox change.

You could try something like this. You will need to change this code according to your usage, here I am assuming, this.getParams('color') will return an array of all the selected colors.

constructor state init

constructor(props) {
  super(props);

  this.state = {
    filters: this.getParams('color') // consedering, it will return array
  }
}

default check the checkbox

defaultChecked ={this.state.filters.indexOf(option.text) === -1 ? false : true}
onChange={() => this.toggleCheckbox(option.text)}

for toggling it

// if not present, then add it
// else remove it
toggleCheckbox(option) {
  if (this.state.filters.indexOf(option) === -1) {
    this.setState({
      filters: [...this.state.filters, option]
    })
  } else {
    this.setState({
      filters: this.state.filters.filter(text => text !== option)
    })
  }
}
Sign up to request clarification or add additional context in comments.

Comments

1

You should set the state of the checkbox in the component state, and then update that state when it's clicked. You can set the initial state based on the url on construct or mount.

Something like this:

constructor(props) {
  super(props);

  const isChecked = this.props.match.params.checkbox === 'true';

  this.state = {
    checkbox: isChecked
  }
}

And then in your checkbox:

<input type="checkbox" checked={this.state.checkbox} onChange={() => this._toggleCheckbox()} />

And the method to turn it on and off would be something like:

toggleCheckbox() {
  this.setState({
    checkbox: !this.state.checkbox // will toggle to the opposite of the current state
  });
}

Note that this is has not been tested but has been written based on the information you gave. The principle behind this is what you need to do. It may also be useful to set the state of the checkbox initially within componentDidMount(), rather than constructor(), but that's up to you. The onChange function of the checkbox uses ES6, but you could bind the function if you prefer or do not use ES6 with this._toggleCheckbox().bind(this)

Edit

To update the checkbox when the url is changed, rather than updating it on click, you could change the toggle method to redirect the browser, and then update the checkbox within componentWillReceiveProps. Taken from my own code with react-router you can use 'this.props.match.params' to find the url parameters. I use react-router-dom package to update the url. So for instance:

This will give you access to this.props.history.

import { withRouter } from 'react-router-dom';

toggleCheckbox() {
  // Check the current state of the checkbox and update the url to the opposite
  let toCheck = this.props.match.params.checkbox === 'true' ? 'false' : 'checked';
  this.props.history.push('/?checkbox=' + toCheck);
}

componentWillReceiveProps(newProps) {
  // Check the new url and update the checkbox if it is different from the checkbox state
  if(newProps.match.params.checkbox != this.state.checkbox) {
    this.setState({checkbox: newProps.match.params.checkbox});
  }
}

2 Comments

I think the OP wants the change the url so that the url can be used/saved from the beginning.
Ah I see. Yes it could be updated with a url change lets see. Ill try and add something in

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.