2016-09-26 57 views
2

客户端希望有一个数字滑块组件,允许他选择一个数字以及一个表示“无值”的复选框。当复选框被选中时,滑块应该被禁用,但仍应保留之前选择的配置。如果复选框被选中,如何防止组件更新

http://image.prntscr.com/image/4efc55b8d11a40749bb1e44c4287a709.png

我在使用的惯用实施这个麻烦的阵营有道具和状态的组件的方式。

我预想的两成单个组件,滑块,复选框的一部分,道具这样的:

value : number 
onChange : (newValue : number) => void 

现在,如果没有复选框被选中,然后value是未定义。问题是,因为value也设置滑块的位置,这意味着一旦复选框被选中,位置将被改变 - 我不希望发生这种情况。

问题是,虽然React希望保持所有组件同步,在这种情况下,我们不想让滑块与应用程序的其余部分保持同步。即使value应该是undefined(或null),我们仍然希望滑块位于用户选取的最后一个值上。

解决此问题的正确方法是什么?

+0

没有任何解决方案,解决或帮助您的问题?如果是这样,请将相应的标记标记为“已接受”。谢谢:) – Chris

回答

3

我不知道你的应用程序逻辑是如何工作的,因为你没有共享它,但是你可以使用shouldComponentUpdate()来解决这个问题。

如果shouldComponentUpdate回报false,然后render()将完全跳过,直至下一个状态变化。另外,componentWillUpdate和componentDidUpdate不会被调用。

所以,你可以这样做:

shouldComponentUpdate(nextProps) { 
    if(typeof nextProps.value === 'undefined') return false; //return false if value is undefined 
    return true; //otherwise always return true (this is default) 
} 

这将防止重新渲染的成分,如果value是不确定的。虽然我会建议发送null而不是,因为变量是实际定义的,但没有任何价值。

请注意,这将不会而是根据您的要求禁用滑块 - 它将简单地保持滑块的原始渲染状态。


如果您还希望在复选框被选中时禁用滑块,您可以在这里看到几个选项。这里有一个:

拆分组件到2子组件

这里的想法是,道具直接控制滑块和复选框,不使用state的。如果您想使用Stateless Functional Components,请查看我的指南,了解如何以及如何使用它。

Demo

所以,你的代码将是这样的:

CheckboxSlider:

class CheckboxSlider extends React.Component { 

    constructor(props, context) { 
    super(props, context); 
    this.state = { 
     value: 50, //default is in the middle, 50% 
     disabled: false 
    }; 
    } 

    _toggleSlider =() => { 
    this.setState({disabled: !this.state.disabled}); 
    } 

    render() { 
    <div> 
     <Slider value={this.state.value} disabled={this.state.disabled} /> 
     <CheckBox onCheckboxChange={this._toggleSlider} /> 
    </div> 
    } 
} 

export default CheckboxSlider; 

滑块:

import React from 'react'; 

const Slider = (props) => (
    <input id="slider" type="range" min="0" max="100" disabled={props.disabled} /> 
); 

export default Slider; 

复选框:

import React from 'react'; 

const Checkbox = (props) => (
    <input id="checkbox" type="checkbox" onChange={props.onCheckboxChange} /> 
); 

export default Checkbox; 
+0

'if(!nextProps.value ==='undefined')return false;'将阻止所有组件更新。 – elmeister

+0

@elmeister的确如此。那里好眼睛。谢谢。 – Chris

+0

还有一件事 - 请在'(!nextProps.value ==='undefined')中添加'typeof'',并将相等的检查改为'!== – elmeister

0

使用单独状态有滑块输入的值,以启用/禁用滑块和检查/取消选中的复选框。以下是一个示例代码片段。

class Slider extends React.Component { 
 

 
    constructor(props) { 
 
    super(props) 
 
    this.state = { 
 
     sliderValue: 100, 
 
     checkedValue: false, 
 
     enable: false 
 
    } 
 
    } 
 
    handleChange= (e) => { 
 
    this.setState({sliderValue: e.target.value}); 
 
    } 
 
    handleClick = (e) => { 
 
    if(this.state.checkedValue == false) { 
 
     this.setState({checkedValue: true, enable: true}, function() { 
 
      this.refs.slider.disabled = true; 
 
     }.bind(this)); 
 
    } else if(this.state.checkedValue == true) { 
 
     this.setState({checkedValue: false, enable: false}); 
 
    } 
 
    } 
 
    render() { 
 
    return (
 
     <div> 
 
     <input type="range" ref="slider" value={this.state.sliderValue} onChange={this.handleChange} min="100" max="500" step="10" disabled={this.state.enable}/> 
 
     <input type="checkbox" onChange={this.handleClick} /> 
 
     </div> 
 
    ) 
 
    } 
 

 
} 
 

 
ReactDOM.render(<Slider />, document.getElementById('app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.8/react.min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.8/react-dom.min.js"></script> 
 
<div id="app"></div>