使用HOC时,从外部渲染更新React状态?

时间:2018-02-15 18:58:59

标签: reactjs

我正在创建一个React小部件并使用react-jss HOC进行样式设置。小部件只是较大页面的一小部分,我希望能够通过React渲染之外的页面另一部分上的按钮来打开或关闭它。最初我这样做是这样的:

var modal = ReactDOM.render(<Modal />, document.getElementById('widget'))

// Inside an onClick function
modal.toggleModal()

那是在JSS之前,但现在widget没有返回组件,它返回JSS HOC。我已经尝试传递<Widget />道具并更新,然后使用widget.forceUpdate()但这没有做任何事情。目前还不确定还有什么可以尝试的。我目前只是在React之外切换所有内容,但我希望该组件能够自行关闭。

import React, { Component } from 'react'
import injectSheet from 'react-jss'

const styles = {
  show: {
    display: 'block',
  },
  modal: {
    display: 'none',
    background: 'rgba(0, 0, 0, 0.3)',
    position: 'fixed',
    top: 0,
    left: 0,
    bottom: 0,
    right: 0,
    width: '100%',
    height: '100%',
  },
  form: {
    maxWidth: '440px',
    margin: '15px',
    padding: '30px',
    background: '#fff',
    position: 'fixed',
    top: '50%',
    left: '50%',
    transform: 'translate(-50%, -50%)'
  },
  input: {
    width: '100%',
    marginBottom: '15px'
  },
  button: {
    width: '100%'
  }
}

class Modal extends Component {
  constructor(props) {
    super(props)

    this.state = {
        show: false
    }

    this.toggleModal = this.toggleModal.bind(this)
  }

  toggleModal() {
      this.setState({show: !this.state.show})
  }  

  render() {
    const { classes } = this.props

    return (
      <div className={`${classes.modal} ${this.state.show ? classes.show : ''}`}>
        <form className={classes.form}>
          <label htmlFor="aatitle-field">Title</label>
          <input className={classes.input} type="text" id="aatitle-field" name="title" value="" />
          <button className={`btn ${classes.button}`}>Save</button>
        </form>
      </div>
    )
  }
}

export default injectSheet(styles)(Modal)

1 个答案:

答案 0 :(得分:-1)

首先,请使用classnames库生成classNames,它更优雅。

其次,应用类以便由浏览器解析它们。所以你正在做的事很棘手。我们如何知道在modal之前是否解析了show类? (这是您当前代码中的要求)。你可以简单地在styles中的show声明之前移动模态声明,这肯定会有效,但这是一个脆弱的解决方案。更好的方法是使用showhide类并根据州应用它们。这将删除首先加载样式类的依赖关系。从display:none移除modal并引入hide:

类似的东西:

import React, { Component } from 'react'
import injectSheet from 'react-jss'

const styles = {
  show: {
    display: 'block',
  },
  hide: {
    display: 'none',
  },
  modal: {
    background: 'rgba(0, 0, 0, 0.3)',
    position: 'fixed',
    top: 0,
    left: 0,
    bottom: 0,
    right: 0,
    width: '100%',
    height: '100%',
  },
  form: {
    maxWidth: '440px',
    margin: '15px',
    padding: '30px',
    background: '#fff',
    position: 'fixed',
    top: '50%',
    left: '50%',
    transform: 'translate(-50%, -50%)'
  },
  input: {
    width: '100%',
    marginBottom: '15px'
  },
  button: {
    width: '100%'
  }
}

class Modal extends Component {
  constructor(props) {
    super(props)

    this.state = {
        show: false
    }

    this.toggleModal = this.toggleModal.bind(this)
  }

  toggleModal() {
      this.setState({show: !this.state.show})
  }  

  render() {
    const { classes } = this.props

    return (
      <div className={`${classes.modal} ${this.state.show ? classes.show : classes.hide}`}>
        <form className={classes.form}>
          <label htmlFor="aatitle-field">Title</label>
          <input className={classes.input} type="text" id="aatitle-field" name="title" value="" />
          <button className={`btn ${classes.button}`}>Save</button>
        </form>
      </div>
    )
  }
}

export default injectSheet(styles)(Modal)

```