从父级更改子组件的状态(使用React的独占可点击框组件)

问题描述 投票:2回答:1

我正在写一个Box组件

  • 显示一个div框
  • 当鼠标指针打开/关闭组件时,框的CSS样式需要不同
  • 当我点击该框时,其样式必须更改以指示它已打开

我写了这个组件,它工作正常。

现在我想改进我的组件。我需要在我的父页面上显示多个Box,当我点击一个Box时,我想重置其余Box组件显示在父级上的状态,所以当我在盒子之间移动鼠标时,他们的样式需要更改,当我点击时其中一个然后选择Box的边框需要改变。

这是Box组件:

const STYLE = {
  boxMouseOver: {...},
  boxMouseOut: {...},
  boxOn: {...},
}

export default class ClickableBox extends React.Component {
  constructor (props) {
    super(props)
    this.state = {
      mouseOver: false,
      turnOn: false
    }
  }

  handleMouseOver = () => {
    this.setState({
      mouseOver: true
    })
  }

  handleMouseOut = () => {
    this.setState({
      mouseOver: false
    })
  }

  handleOnClick = () => {
    this.setState({
      turnOn: !this.state.turnOn
    });

    this.props.resetStateCallback();
  }

  resetState = () = => {
    this.setState({
      turnOn: false
    });
  }

  render () {
    let style = this.state.mouseOver ? STYLE.boxMouseOver : STYLE.boxMouseOut
    style = this.state.turnOn ? STYLE.boxOn : style

    return (
      <div style={style} onMouseOver={this.handleMouseOver} onMouseOut={this.handleMouseOut} onClick={this.handleOnClick}>
        <span style={STYLE.title}>{this.props.title}</span>
        <br/>{this.state.turnOn ? "on" : "off"}
      </div>
    )
  }
}

这是父组件:

export default class GroupOfBoxes extends React.Component {
  reset () {
    alert('reset')

    // **** I need help for this part ****
    // Need to be called resetState() method on
    // ClickableBox components shows on this page
    for (currentBox : ?????) {
       if (currentBox != selected Box??) {
          currentBox.resetState()
       }
    }
  }

  render () {
    return (
      <div>
        <Grid>
          <Row className='show-grid'>
            <Col sm={12}>
              <ClickableBox title='1' resetStateCallback={this.reset} />
              <ClickableBox title='2' resetStateCallback={this.reset} />
              <ClickableBox title='3' resetStateCallback={this.reset} />
              <ClickableBox title='4' resetStateCallback={this.reset} />
            </Col>
          </Row>
          <Row className='show-grid'>
            <Col sm={12}>
              <ClickableBox title='5' resetStateCallback={this.reset} />
              <ClickableBox title='6' resetStateCallback={this.reset} />
              <ClickableBox title='7' resetStateCallback={this.reset} />
              <ClickableBox title='8' resetStateCallback={this.reset} />
            </Col>
          </Row>
        </Grid>
      </div>
    )
  }
}

我不知道从父页面更改Box组件状态,因为我需要在父页面上引用我的Box组件,并在ClickableBox.resetState()方法的每个ClickableBox组件上调用GroupOfBoxes.reset()方法。

----更新----

在我阅读了更多与React相关的文档后,我能够使我的代码工作,但我认为我的解决方案远非最佳。我将不胜感激任何优化的帮助。

所以我使用ref属性来获取对我的Box组件的引用,并且我写了很多条件来决定需要重置哪些Box组件:

首先,我对ClickableBox组件进行了更改,我在resetStateCallback方法调用中添加了一个'this'参数:

handleOnClick = () => {
  this.setState({
    turnOn: !this.state.turnOn
  });

  this.props.resetStateCallback(this);
}

然后我将ref键添加到父组件:

<ClickableBox ref='box1' title='1' body='...' footer='...' resetStateCallback={this.reset} />
<ClickableBox ref='box2' title='2' body='...' footer='...' resetStateCallback={this.reset} />
...

最后我在父组件上修改了reset()方法:

(这种方法看起来很难看,所以如果可以,请帮我优化一下)

reset(comp) {
  if (comp.props.title === '1') {
    this.refs.box2.resetState()
    this.refs.box3.resetState()
    this.refs.box4.resetState()
    this.refs.box5.resetState()
    this.refs.box6.resetState()
    this.refs.box7.resetState()
    this.refs.box8.resetState()
  } else if (comp.props.title === '2') {
    this.refs.box1.resetState()
    this.refs.box3.resetState()
    this.refs.box4.resetState()
    this.refs.box5.resetState()
    this.refs.box6.resetState()
    this.refs.box7.resetState()
    this.refs.box8.resetState()
  } else if (comp.props.title === '3') {
    this.refs.box1.resetState()
    this.refs.box2.resetState()
    this.refs.box4.resetState()
    this.refs.box5.resetState()
    this.refs.box6.resetState()
    this.refs.box7.resetState()
    this.refs.box8.resetState()
  } else if (comp.props.title === '4') {
    ...
  } else if (comp.props.title === '5') {
    ...
  } else if (comp.props.title === '6') {
    ...
  } else if (comp.props.title === '7') {
    ...
  } else if (comp.props.title === '8') {
    ...
  }
}
reactjs react-native
1个回答
0
投票

我会把所有的盒子包在BoxWrapper里面。 BoxWrapper在其州有两个属性:mouseOverIndexclickedIndex

它将这个状态传递给它的孩子。这样,所有逻辑都保存在包装器中,而Box不需要知道其兄弟姐妹的状态。

https://jsfiddle.net/20kpgjcj/3/

© www.soinside.com 2019 - 2024. All rights reserved.