While working on a React Component, I'm trying to set a specific range of values to determine the step
on a type range input.
I'm able to reproduce the desired behavior with vanilla HTML and JS i.e.
HTML
<!-- custom step range -->
<div class="step">
<input id="input" type="range" min="0" value="0" max="4" step="1" list="tick-list">
<datalist id="tick-list">
<option>0</option>
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
</datalist>
<span id="output"></span>
</div>
JS
var values = [10,25,50, 75, 100];
var input = document.getElementById('input'),
output = document.getElementById('output');
input.oninput = function(){
output.innerHTML = values[this.value];
};
input.oninput();
see codepen here
However, not able to achieve the same results when trying to wire this same functionality to React.
i.e.
class App extends Component {
constructor() {
super();
this.state = {
values : [10, 25, 50, 75, 100]
};
}
handleInputChange = () => {
const input = document.querySelector('input'),
const output = document.getElementById('output');
output = this.state.values;
};
render() {
return (
<div>
<input
oninput={this.handleInputChange()}
type="range"
min="0"
value="0"
max="4"
step="1"
list="tick-list" />
<datalist id="tick-list">
<option value="0" />
<option value="1" />
<option value="2" />
<option value="3" />
<option value="4" />
</datalist>
<span id="output">{this.state.values}</span>
</div>
);
}
}
render(<App />, document.getElementById('root'));
The above doesn't let me move the slide nor outputs the steps one at time.
How could I wire this properly using React JS? Ps: Feel free to provide an example as a functional ponent rather than a class.
While working on a React Component, I'm trying to set a specific range of values to determine the step
on a type range input.
I'm able to reproduce the desired behavior with vanilla HTML and JS i.e.
HTML
<!-- custom step range -->
<div class="step">
<input id="input" type="range" min="0" value="0" max="4" step="1" list="tick-list">
<datalist id="tick-list">
<option>0</option>
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
</datalist>
<span id="output"></span>
</div>
JS
var values = [10,25,50, 75, 100];
var input = document.getElementById('input'),
output = document.getElementById('output');
input.oninput = function(){
output.innerHTML = values[this.value];
};
input.oninput();
see codepen here
However, not able to achieve the same results when trying to wire this same functionality to React.
i.e.
class App extends Component {
constructor() {
super();
this.state = {
values : [10, 25, 50, 75, 100]
};
}
handleInputChange = () => {
const input = document.querySelector('input'),
const output = document.getElementById('output');
output = this.state.values;
};
render() {
return (
<div>
<input
oninput={this.handleInputChange()}
type="range"
min="0"
value="0"
max="4"
step="1"
list="tick-list" />
<datalist id="tick-list">
<option value="0" />
<option value="1" />
<option value="2" />
<option value="3" />
<option value="4" />
</datalist>
<span id="output">{this.state.values}</span>
</div>
);
}
}
render(<App />, document.getElementById('root'));
The above doesn't let me move the slide nor outputs the steps one at time.
How could I wire this properly using React JS? Ps: Feel free to provide an example as a functional ponent rather than a class.
Share Improve this question edited Aug 21, 2019 at 21:27 Null isTrue asked Aug 21, 2019 at 21:06 Null isTrueNull isTrue 1,9368 gold badges31 silver badges50 bronze badges 4- Try this method: stackoverflow./questions/45167565/… – inertia Commented Aug 21, 2019 at 21:12
- Perhaps using onChange instead of onInput – inertia Commented Aug 21, 2019 at 21:13
- I tried onChange no dice. I'm wondering how to refactor from the working vanilla JS ex I posted to React. – Null isTrue Commented Aug 21, 2019 at 21:16
- Set the output to a state and output using the state. – inertia Commented Aug 21, 2019 at 21:20
2 Answers
Reset to default 2In this case you can make use of state
in React to store the current index of your stepped input ponent, rather than finding the output DOM node and changing it's inner HTML.
Which would makes your handleInputChange
function:
handleInputChange = e => {
this.setState({ currentStep: e.currentTarget.value });
};
React operates on it's own virtual DOM, it changes the names of the HTML attributes on the DOM nodes to a React equivalent -> https://reactjs/docs/dom-elements.html.
Which means you'll need to change oninput
to onInput
in your ponent.
Here is one possible working version of your React ponent:
import React from "react";
import { render } from "react-dom";
class App extends React.Component {
values = [10, 25, 50, 75, 100];
constructor(props) {
super(props);
this.state = {
currentStepIndex: 0
};
}
handleInputChange = e => {
this.setState({ currentStepIndex: e.currentTarget.value });
};
render() {
return (
<div>
<input
onInput={this.handleInputChange}
type="range"
min="0"
value={this.state.currentStepIndex}
max="4"
step="1"
list="tick-list"
/>
<datalist id="tick-list">
<option>0</option>
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
</datalist>
<span id="output">{this.values[this.state.currentStepIndex]}</span>
</div>
);
}
}
render(<App />, document.getElementById("root"));
code sandbox
Here is a working example for your react range:
class App extends Component {
constructor() {
super();
this.state = {
rangeValues: [10, 25, 50, 75, 100],
currentRangeValue: 0
};
this.handleInputChange = this.handleInputChange.bind(this);
}
handleInputChange = (e) => {
this.setState({ currentRangeValue: e.target.value });
};
render() {
const { rangeValues, currentRangeValue } = this.state
return (
<div>
<input
onChange={this.handleInputChange}
type={"range"}
min={0}
defaultValue={0}
max={4}
step={1}
list={"tick-list"} />
<datalist id="tick-list">
<option>0</option>
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
</datalist>
<span id="output">{rangeValues[currentRangeValue]}</span>
</div>
);
}
}
Check it here: https://codesandbox.io/s/morning-water-z6fjv?fontsize=14