0

I have a parent component with an object which contains some nested arrays that represent a range:

    class ParentComponent extends React.Component {

        constructor() {
                super();
                this.state = {
                    filters: {
                        rangeArray1: [0, 2000],
                        rangeArray2: [0, 5000]
                       // and many other similar nested arrays
                    }
                } 
            }

          //this gives TypeError: Cannot read property 'name' of undefined
          //it works if there were nested objects instead of arrays
          handleFilterChange = (e) => {
            this.setState({
                filters: {
                    ...this.state.filters,
                    [e.target.name]: e.target.value,
                }
            })
        }

          //this works, but I need a method that handles all the arrays
          handleFilterChange = (e) => {
            this.setState({
                filters: {
                    ...this.state.filters,
                    rangeArray1: e.value,
                }
            })
        }

        //render method omitted     
     }

I also have a deeper nested child component, which handles filtering by the ranges using a range slider:

        class GrandchildComponent extends React.Component {

                handleFilterChange = e => {
                    this.props.handleFilterChange && this.props.handleFilterChange(e)
                };

                render() {
                    return (
                        <div>
                             <p>Range1: {this.props.filters.rangeArray1[0]} - {this.props.filters.rangeArray1[1]}</p>
                             <Slider id="rangeArray1"
                                     value={this.props.filters.rangeArray1}
                                     name="rangeArray1"
                                     onChange={this.handleFilterChange}/>

                             <p>Range2: {this.props.filters.rangeArray2[0]} - {this.props.filters.rangeArray2[1]}</p>
                             <Slider id="rangeArray2"
                                     value={this.props.filters.rangeArray2}
                                     name="rangeArray2"
                                     onChange={this.handleFilterChange}/>

                             //and many other similar sliders
                        </div>
                    )
                }
            }

I have a situation where the user filters some data using range sliders and I am trying to send the inputs up to my parent component using a callback method handleFilterChange. I am having trouble creating a method that can handle all the arrays in my object. I added some sample code that I have tried, but both my examples have some flaws.

I am using Primereact slider component

User3000
  • 65
  • 1
  • 12
  • Can you provide how are you passing `handleFilterChange` as prop from `ParentComponent` component – Ashish Apr 21 '20 at 11:25
  • Hey @User3000, I created a [sandbox](https://codesandbox.io/s/lingering-firefly-ng4qz?file=/src/App.js) to test this. Is this what you're looking for? – Ajin Kabeer Apr 21 '20 at 11:32
  • @Ashish `handleFilterChange` is passed to child in render as `` – User3000 Apr 21 '20 at 11:45
  • @AjinKabeer I am not sure what you mean by testing. I am looking for a solution as I am a bit stuck at the moment. – User3000 Apr 21 '20 at 11:48
  • Can you provide the `onChange` implementation of `Slider` component? because looks like `event.target` is `undefined`. Alternatively you can use `console.log(e)` inside `handleFilterChange` to debug. – Ashish Apr 21 '20 at 11:57
  • @Ashish I am using Primereact UI library. -> [slider component](https://primefaces.org/primereact/showcase/#/slider) – User3000 Apr 21 '20 at 11:59
  • Add the link to this component in your question. I have added the answer, you can check, it should work. – Ashish Apr 21 '20 at 12:11

1 Answers1

1

As per the documentation of Slider component you are using. the parameters for onChange callback function is an object with keys originalEvent: Slide event and value: New value. So to access target you need to use event.originalEvent.target.

so change your function like this:

handleFilterChange = (e) => {
    this.setState({
        filters: {
            ...this.state.filters,
            [e.originalEvent.target.name]: e.value,
        }
    })
}

The other way is if you don't want to use e.target so instead of using the name from e.target you can pass it directly to the function

Inside Parent Component:

handleFilterChange = (sliderName, value) => {
    this.setState({
        filters: {
            ...this.state.filters,
            [sliderName]: value,
        }
    })
}

child component:

class GrandchildComponent extends React.Component {
    handleFilterChange = (name, value) => {
        this.props.handleFilterChange && this.props.handleFilterChange(name, value)
    };
    render() {
        return (
            <div>
                <p>Range1: {this.props.filters.rangeArray1[0]} - {this.props.filters.rangeArray1[1]}</p>
                <Slider id="rangeArray1"
                    value={this.props.filters.rangeArray1}
                    onChange={(e) => this.handleFilterChange(
                        'rangeArray1', e.value
                    )}
                />

               //and many other similar sliders
            </div>
        )
    }
}
Ashish
  • 4,206
  • 16
  • 45