我正在使用React.JS进行构建,并且正在构建一个范围输入滑块,其中包含两个组件选项。
这是我的代码:
<input id="typeinp" type="range" min="0" max="5" value="3" step="1"/>
当我将它放入我的客户端渲染组件并尝试切换它时它根本不会移动。测试它到我继续的JS / PHP构建,它工作正常。
为什么这在JSX / React.JS中不起作用以及建议的解决方法是什么?
谢谢!
答案 0 :(得分:32)
用户互动无效,因为<input>
道具value
被视为受控。这意味着显示的值完全由render
函数控制。因此,要实际更新输入值,您应该使用onChange
事件。例如:
getInitialState: function() {
return {value: 3};
},
handleChange: function(event) {
this.setState({value: event.target.value});
},
render: function() {
return (
<input
id="typeinp"
type="range"
min="0" max="5"
value={this.state.value}
onChange={this.handleChange}
step="1"/>
);
}
您也可以使用defaultValue
代替value
。在这种情况下,<input>
被视为不受控制,任何用户互动都会立即被元素本身反映,而无需调用组件的render
功能。
有关官方documentation
的详情答案 1 :(得分:3)
我认为之前的答案可以解决您的问题。但是,我说解决方案并不需要涉及React状态。
冻结输入滑块背后的唯一原因是你已经将其值硬编码为3,正如@Colin Whitmarsh建议的那样。
简单地说,这有效:
<input id="typeinp" type="range" min="0" max="5" defaultValue="3" step="1"/>
现在,您可能需要其输出来执行某些操作。您可以在答案中使用onChange={this.handleChange}
作为@xCrZx状态。但在handleChange
内,你不一定要更新你的州。根据您的逻辑,您可以避免增加状态的复杂性,只需在handleChange
内编写逻辑代码。
如果你避免更新状态,你可能会保存一些渲染,你的表现会有所改善。
答案 2 :(得分:1)
试试这个:
onInput() {
var input = document.getElementById("typeinp");
var currentVal = input.value;
this.setState({
value: currentVal
})
}
<input id="typeinp" type="range" min="0" max="5" step="1" defaultValue="3" onInput={this.onInput.bind(this)}/>
我建议改变价值=&#34; 3&#34;到 defaultValue =&#34; 3&#34; ,否则我认为价值被硬编码为&#34; 3&#34;可能很难或不可能改变。 onInput函数查找该值并将其添加到state,以便将数据传递给另一个组件或函数。对您的问题可能有一个更优雅的解决方案,但上述方法应该有效。
答案 3 :(得分:1)
我希望以上解决方案可以解决您的问题,我有一种使用钩子的简单方法。
const RangeSlider = () => {
const [rangeval, setRangeval] = useState(null);
return (
<div>
<input type="range" className="custom-range" min="199" max="3999"
onChange={(event) => setRangeval(event.target.value)} />
<h4>The range value is {rangeval}</h4>
</div>
);
};
export default RangeSlider;
答案 4 :(得分:0)
这是一个解决方案,用于制作多个滑块的形式,甚至是传递了事件处理程序的单个滑块
我们可以简单地使用Range类型的HTML输入
rc-slider和react-input-range未发送事件处理程序 onChange
或onAfterChange
他们隐式发送了滑块的值,因此我们不能处理滑块的形式或动态创建它们。
有关详情,我们可以查看HTML input Range
提供的CSS-Tricks和CSS
class SlidersExample extends React.Component {
constructor(props) {
super(props);
this.state = {
slidersLabels: ["A", "B", "C", "D"],
sumOfCustomWeights: 0,
slidersWeights: []
};
}
componentDidMount() {
const slidersLabels = this.state.slidersLabels;
const slidersWeights = [];
for (var i = 0; i < slidersLabels.length; ++i)
slidersWeights[slidersLabels[i]] = 0;
this.setState({ slidersWeights });
}
render() {
return (
<div>
{this.generateSliders()}
<span> Total Weights: {this.state.sumOfCustomWeights} </span>
</div>
);
}
generateSliders() {
const slidersLabels = this.state.slidersLabels;
var sliders = [];
for (var i = 0; i < slidersLabels.length; ++i) {
sliders.push(
<div style={{ marginTop: "20px", marginBottom: "20px" }}>
<span style={{ fontSize: "16px", marginBottom: "6px" }}>
{" "}
{slidersLabels[i]} ({this.state.slidersWeights[slidersLabels[i]]})%
</span>
<input
id={slidersLabels[i]}
type="range"
defaultValue="0"
min="0"
max="100"
className="slider"
onChange={this.handleSliderChange.bind(this)}
step="1"
/>
</div>
);
}
return sliders;
}
handleSliderChange(event) {
//console.log(event.target.value, " ", event.target.id);
var id = event.target.id;
var value = event.target.value;
const slidersWeights = this.state.slidersWeights;
slidersWeights[id] = parseInt(value);
var sumOfCustomWeights = 0;
const slidersLabels = this.state.slidersLabels;
for (var i = 0; i < slidersLabels.length; i++)
sumOfCustomWeights += slidersWeights[slidersLabels[i]];
this.setState({ slidersWeights, sumOfCustomWeights });
}
}
ReactDOM.render(<SlidersExample />, document.querySelector("#app"));
&#13;
input[type=range] {
-webkit-appearance: none;
margin: 18px 0;
width: 100%;
}
input[type=range]:focus {
outline: none;
}
input[type=range]::-webkit-slider-runnable-track {
width: 100%;
height: 8.4px;
cursor: pointer;
animate: 0.2s;
box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d;
background: #3071a9;
border-radius: 1.3px;
border: 0.2px solid #010101;
}
input[type=range]::-webkit-slider-thumb {
box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d;
border: 1px solid #000000;
height: 36px;
width: 16px;
border-radius: 3px;
background: #ffffff;
cursor: pointer;
-webkit-appearance: none;
margin-top: -14px;
}
input[type=range]:focus::-webkit-slider-runnable-track {
background: #367ebd;
}
input[type=range]::-moz-range-track {
width: 100%;
height: 8.4px;
cursor: pointer;
animate: 0.2s;
box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d;
background: #3071a9;
border-radius: 1.3px;
border: 0.2px solid #010101;
}
input[type=range]::-moz-range-thumb {
box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d;
border: 1px solid #000000;
height: 36px;
width: 16px;
border-radius: 3px;
background: #ffffff;
cursor: pointer;
}
input[type=range]::-ms-track {
width: 100%;
height: 8.4px;
cursor: pointer;
animate: 0.2s;
background: transparent;
border-color: transparent;
border-width: 16px 0;
color: transparent;
}
input[type=range]::-ms-fill-lower {
background: #2a6495;
border: 0.2px solid #010101;
border-radius: 2.6px;
box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d;
}
input[type=range]::-ms-fill-upper {
background: #3071a9;
border: 0.2px solid #010101;
border-radius: 2.6px;
box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d;
}
input[type=range]::-ms-thumb {
box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d;
border: 1px solid #000000;
height: 36px;
width: 16px;
border-radius: 3px;
background: #ffffff;
cursor: pointer;
}
input[type=range]:focus::-ms-fill-lower {
background: #3071a9;
}
input[type=range]:focus::-ms-fill-upper {
background: #367ebd;
}
#app{
margin-right: 100px;
margin-left: 100px;
margin-bottom: 100px;
}
&#13;
<!DOCTYPE html>
<html>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"> </div>
</body>
</html>
&#13;
此解决方案与我完美配合;)