首页 文章

如何在React组件上管理状态,该组件可以从父级或事件中的事件更改状态?

提问于
浏览
5

我正在尝试创建一个自定义复选框组件(实际上是一个三态,但除了说我不只是使用INPUT之外,这是无关紧要的),我不知道如何让它能够改变“ “检查”来自对自身的点击以及来自父母的 Value 集 .

目前,我让它作为一个自给自足的组件工作,它接受一个onChange prop与它调用的处理程序回调,以便在点击后发送父组件的值 . 它使用状态来存储由显示器引用的检查 .

如果它只是一个检查的显示,从外部管理 Value ,我就像我一样使用状态,但我的问题是我希望它可以点击以打开和关闭,并允许父母转向它也是开关的 .

我是React的初学者和“React的思维方式”所以我怀疑我只是接近这个错误 . 我得到的印象是,这样做的正确方法是将它作为一个仅显示组件,将点击向上传递给父级进行处理,然后从父级接收到值更改的道具更新,但是在我看来,这会使组件的可重用性降低 .

那么我将如何从内部和父源进行复选框更改?

我们也欢迎相关链接 .

3 回答

  • 7

    您可以将复选框视为一个哑组件,这意味着它不包含任何内部状态,但只通过道具从外部接收数据然后再渲染它们 . 你可以看到哑组件here的详细定义 .

    同时,当单击该复选框时,此类事件将由组件的父级或事件祖先处理,这称为逆数据流,这在Facebook的Thinking in React博客文章中有所描述 .

    此外,为了确定哪个组件应该具有某些状态,我发现以下指南非常有用:

    请记住:React是关于组件层次结构中的单向数据流 . 可能不会立即清楚哪个组件应该拥有哪个状态 . 这通常是新手理解中最具挑战性的部分,因此请按照以下步骤进行解决:对于应用程序中的每个状态:确定基于该状态呈现某些内容的每个组件 . 查找公共所有者组件(在层次结构中需要状态的所有组件上方的单个组件) . 公共所有者或层次结构中较高层的其他组件应该拥有该状态 . 如果找不到拥有状态的组件,只需创建一个新组件来保存状态,并将其添加到公共所有者组件上方的层次结构中的某个位置 .

    伪代码片段:

    const Checkbox = React.createClass({
      // Propagate the event to parents
      onClick(evt) {
        if (this.props.handleClick) {
          this.props.handleClick({checked: evt.target.value});
        }
      },
    
      render() {
        return (
          this.props.checked ? 
            <Input onClick={this.onClick} type="checkbox" label="Checkbox" checked></Input> : 
            <Input onClick={this.onClick} type="checkbox" label="Checkbox"></Input>
        );
      }
    });
    
    const Container = React.createClass({
      handleClick(evt) {
        // Change the container's state, which eventually changes the checkbox's view via props.
        this.setState({checked: evt.checked});
      },
    
      render() {
        return (
          <div><Checkbox checked={this.state.checked} handleClick={this.handleClick}></Checkbox></div>
        );
      }
    });
    
  • -2

    您只从父级更改它 .

    class ParentComponent extends React.Component{
      handleChildCheck(){
        this.setState({
         childChecked: !this.state.childChecked
        })
      }
      render(){
        return(
          <ChildComponent checked={this.state.childChecked} handleCheck={this.handleChildCheck.bind(this)} />
        )
     }
    }
    

    现在,如果您希望从 <ChildComponent/> 控制已检查状态,只需从 <ChildComponent/> 调用 this.props.handleCheck()

    这样,控件将始终在 <ParentComponent/> 中通过 this.props.handleCheck() this.handleChildCheck() 中的 <ChildComponent/> 中可用 .

  • 3

    使用querySelectorAll查找组件 . 添加事件侦听器以监视更改 . 在更改时运行另一个querySelectorAll来查找子项并禁用或启用 . 这可能无法满足您的所有需求,但它会让您开始朝着正确的方向前进 . 这是普通的JavaScript,因此不需要其他库 .

    // Finds radios with class on-off and disables 'name-on' elements when
    // 'name' is off.
    
    function initOfOff() {
      var mains = document.querySelectorAll('.on-off');
    
      for (var i = 0; i < mains.length; i++) {
        var el = mains[i];
        var name = el.getAttribute('name');
        el.addEventListener('click', function() {
          var value = this.getAttribute('value');
          var children = document.querySelectorAll('.' + name + '-on');
          for (var i = 0; i < children.length; i++) {
            var child = children[i];
            child.checked = false;
            if (value == "off") {
              child.setAttribute('disabled', 'disabled');
            } else {
              child.removeAttribute('disabled');
            }
          }
        });
      }
    }
    initOfOff()
    
    <form name='myform'>power
      <input type='radio' value='on' class='on-off' name='power'>ON |
      <input type='radio' value='off' class='on-off' name='power'>Off
      <dir>lights
    
        <input type='radio' value='on' class='power-on' name='lights'>ON |
        <input type='radio' value='off' class='power-on' name='lights'>OFF
      </dir>
    </form>
    

相关问题