1

I have a select filter, I want to filter my products by category. The state gets updated but the callback of setState is not executed. Basically I want to update my list immediately when the state is changed. Code line 31 doesn't get executed in the try blok, it's also not catching any error.

HTML

<div className="col-md-4 w-25 mt-3 ml-5">
                <Select
                  onChange={this.handleChange}
                  value={selectedCategory}
                  placeholder="Select Category"
                  options={categories}
                />
   </div>

JavaScript

    handleChange = event => {
    console.log(event.value);
    this.setState({ selectedCategory: event.value }, () => {
      try {
        products.pipe(
          map(products =>
            products
              .filter(
                product => product.category === this.state.selectedCategory
              )
              .subscribe(products => {
                console.log(products);
                this.setState({
                  items: products,
                  isLoaded: true
                });
              })
          )
        );
      } catch (error) {
        console.error(error);
      }
    });
  };

enter image description here

Muj
  • 132
  • 3
  • 14
  • `this.setState(() => return {}, () => {callback here})` – demkovych Feb 18 '20 at 16:33
  • 2
    It's being executed, but your `this.state` and `this.setState()` are getting the context from the wrong source because you used `function() {` instead of `() => {` – Patrick Roberts Feb 18 '20 at 16:33
  • It's still unclear what you're trying to accomplish and what is not working. Please update the question description with more details. Also include a [mcve], the code snippet currently in the question is missing a lot of dependencies to be reproducible. – Emile Bergeron Feb 18 '20 at 16:34
  • 1
    @EmileBergeron I think it's pretty clear. It _appears_ as if it's not executing because `this` is not what they think it is, so the `.filter()` probably returns `false` for every category. – Patrick Roberts Feb 18 '20 at 16:36
  • @PatrickRoberts It's still not minimal, but I see now that it's obvious. Missed it while quickly skimming over the code. Though I'm wondering why it's not failing with either `state` or `selectedCategory` not being properties of undefined? – Emile Bergeron Feb 18 '20 at 16:50
  • 1
    @EmileBergeron `this` might be `window` and `state` might happen to be a global variable in their application? Just a guess. Another possibility is that rxjs catches the exception thrown in `filter()` and emits an `onerror` message from the observable. – Patrick Roberts Feb 18 '20 at 17:19
  • @PatrickRoberts I already tried your solution, but had no luck. I forgot to delete the function before posting it. During debuging it jumps from the code product.pipe oprator and the DOM also doesn't rerender. – Muj Feb 18 '20 at 17:22
  • 1
    @Muj if it doesn't work for you, then [edit] your question with the code you actually did try as a [mcve] like Emile has requested above, and flag your question to be reopened. – Patrick Roberts Feb 18 '20 at 17:25

2 Answers2

0

This code did the trick, still don't know why it was not working. Can anybody explain this?

handleChange = event => {

      this.setState(
        { selectedCategory: event.value },
        this.showFilteredProducts
      );
  };

  showFilteredProducts() {
    const filterItems = products.pipe(
      map(products =>
        products.filter(
          product => product.category === this.state.selectedCategory
        )
      )
    );
    filterItems.subscribe(products => {
      this.setState({
        items: products,
        isLoaded: true
      });
    });
  }
Muj
  • 132
  • 3
  • 14
-1
  handleChange = event => {
    console.log(event.value);
    this.setState({ selectedCategory: event.value }, () => { // this line right here
      products.pipe(
        map(products =>
          products
            .filter(product => product.category === this.state.selectedCategory)
            .subscribe(products => {
              console.log(products);
              this.setState({
                items: products,
                isLoaded: true
              });
            })
        )
      );
    });
  };

Change this line: this.setState({ selectedCategory: event.value }, function() { to this this.setState({ selectedCategory: event.value }, () => {

Calling it 'function' changes the this context.

TKoL
  • 13,158
  • 3
  • 39
  • 73
  • 2
    This is an often-repeated duplicate. – T.J. Crowder Feb 18 '20 at 16:36
  • I already tried your solution, but had no luck. I forgot to delete the function before posting it. During debuging it jumps from the code product.pipe oprator and the DOM also doesn't rerender – Muj Feb 18 '20 at 17:17
  • Have you tried wrapping your `products.pipe(...)` call in a try-catch to see if it's erroring? – TKoL Feb 18 '20 at 17:28