如果选中复选框,如何防止组件更新

时间:2016-09-26 10:58:32

标签: javascript reactjs ecmascript-6

客户希望有一个允许他选择数字的数字滑块组件,以及一个显示“无值”的复选框。选中该复选框后,应禁用滑块,但仍应保留其先前选择的配置。

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

我在使用具有道具和状态的组件的惯用React方法时遇到了麻烦。

我想把这两个作为单个组件的一部分,一个滑块复选框,带有这样的道具:

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

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

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

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

2 个答案:

答案 0 :(得分: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;

答案 1 :(得分: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>