【问题标题】:How to prevent component from updating, if checkbox is checked如果选中复选框,如何防止组件更新
【发布时间】:2017-02-03 16:36:49
【问题描述】:

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

我在使用具有 props 和 state 的组件的惯用 React 方式来实现这一点时遇到了麻烦。

我将两者设想为单个组件的一部分,即滑块复选框,具有如下道具:

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

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

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

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

【问题讨论】:

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

标签: javascript reactjs ecmascript-6


【解决方案1】:

我不知道你的应用程序逻辑是如何工作的,因为你没有分享它,但是你可以使用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

所以你的代码应该是这样的:

复选框滑块:

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;

【讨论】:

  • if(!nextProps.value === 'undefined') return false; 将阻止所有组件更新。
  • 还有一件事 - 请在 (!nextProps.value === 'undefined') 中添加 typeof 并将等号检查更改为 !==
  • @elmeister,这里不需要否定。但是你对typeof 防止异常是正确的......这就是为什么我不鼓励在这里使用undefined - 没有意义。不过再次感谢。
【解决方案2】:

使用单独的状态来获得滑块输入的值,启用/禁用滑块以及选中/取消选中复选框。下面是一个示例 sn-p。

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>

【讨论】:

    猜你喜欢
    • 2012-11-20
    • 2015-02-26
    • 2018-05-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-19
    • 2016-01-11
    • 1970-01-01
    相关资源
    最近更新 更多