5

I'm wondering how you'd go about getting the value of an index in an array using an input[type="range"] in React, similar to this example?

What I'm trying to do is this: pass in a range of values and be able to print out those values by using the index of the array.

As you'll see from the example code below, I am initially rendering the value I want (in this case, 'Apples') but then when I use the slide it then starts rendering the index of the array, instead of the values.

Here's what I've got so far:

class RangeSlider extends React.Component {
  // constructor
  constructor(props) {
    super(props);
    this.state = {
      value: props.value[0]
    };
  }

  handleChange(event, index) {
    const { value } = this.state;
    this.setState({ value: event.target.value});
  }

  render() {
    const { value } = this.state;
    const { label } = this.props;

    return (
      <div className="mb4">
        <label className="f4 mt0">
          {label} <b className="fw7 pl1">{value}</b>
        </label>
        <input
          className="w-100 appearance-none bg-transparent range-slider-thumb-custom"
          type="range"
          min={0}
          max={this.props.value.length - 1}
          step={1}
          value={value}
          onChange={this.handleChange.bind(this)}
        />
      </div>
    );
  }

}

window.onload = () => {
  ReactDOM.render(
    <RangeSlider 
      label={"I would like some "} 
      value={["Apples", "Oranges", "Pears"]} />, 
    document.getElementById("main"));
};

Link to a Codepen.

2
  • 1
    you mean like this codepen.io/maio/pen/qXMVda? Commented Aug 26, 2017 at 14:17
  • @maioman that's exactly it, thank you! 👊 Commented Aug 26, 2017 at 14:28

2 Answers 2

3

The only problem you were having is that on initial load, your state object was set to access the value in the array correctly. However, everytime the handleChange method fires, it overwrites the state with just an integer, and thus does not do what you are expecting.

If you instead just set the "value" property in your state object to a default value of "0", you can just track the index, and change one more line in your code, and it should work just fine.

First change your state to look like this:

this.state = {
  value: 0
};

Next, change to this inside your jsx body:

{label} <b className="fw7 pl1">{this.props.value[value]}</b>

This way, you are always going to print out a value, and not an integer to the screen. I think this results in you having to add far less code.

Working Codepen.

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you, Daniel. I've accepted this as the correct answer due to the simplicity of the code and the detailed explanation. That totally makes sense, cheers!
No problem. Love me some React. Keep the questions coming on SO =D
0

Here is the updated code

import React from 'react'

class Range extends React.Component {
  // constructor
  constructor(props) {
    super(props)
    this.state = {
      value: 0
    }

    this.handleChange = this.handleChange.bind(this)
  }

  handleChange(event) {
    this.setState({ value: this.props.value[event.target.value]})
  }

  render() {
    const { value } = this.state
    const { label } = this.props
    return (
      <div className="mb4">
        <label className="f4 mt0">
          {label} <b className="fw7 pl1">{value}</b>
        </label>
        <input
          className="w-100 appearance-none bg-transparent range-slider-thumb-custom"
          type="range"
          min={0}
          max={this.props.value.length - 1}
          step={1}
          onChange={this.handleChange}
        />
      </div>
    )
  }

}

export default Range

Comments

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.