这是一种反模式 - Reactjs

时间:2017-02-08 07:32:44

标签: javascript reactjs jsx

我刚开始使用React并在一个小应用程序上工作,与此同时我制作了一个小节目并隐藏了模态。我想知道我的做法是错误的做法。如果这是反模式,我应该怎么做呢?

class App extends Component {
   constructor(props) {
      super(props);
      this.state = {show: false};
      this.showModal = this.showModal.bind(this);
   }

   render() {
       return (
           <div>
              <h2 className={styles.main__title}>Helloooo!</h2>
              <Modal ref='show'/> 
              <button onClick={this.showModal} className={styles.addtask}>&#x2795;</button>
           </div>
       );
   }

   showModal(){
       this.setState({
          show: true
       });
       this.refs.show.showModal();
   }

}

我所做的模态组件正在使用这个逻辑,它挂钩dom元素并使用document.queryselector进行修改。这是做出反应中的dom操作的正确方法吗?

我使用的模态代码是:

class Modal extends Component {
constructor() {
    super();
    this.hideModal = this.hideModal.bind(this);
    this.showModal = this.showModal.bind(this);
    this.state = { modalHook: '.'+styles.container };
}

render() {
    return (
        <div>
            <div onClick={this.hideModal} className={styles.container}>
                <div className={styles.container__content}>
                    <div className={styles.card}>
                        <div className={styles.card__header}>
                            <h2>Add new task</h2>
                        </div>
                        <div className={styles.card__main}>
                            <Input type="text" placeholder="enter the task title" />
                            <Input type="textarea" placeholder="enter the task details" />
                        </div>
                        <div className={styles.card__actions}>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    );
}

showModal(){
    let container = document.querySelector(this.state.modalHook);
    container.classList.add(styles.show);    
}
hideModal(e){
    let container = document.querySelector(this.state.modalHook);
    if(e.target.classList.contains(styles.container)){
        container.classList.remove(styles.show);
    }
}
}

2 个答案:

答案 0 :(得分:2)

您的示例看起来很简单,但相应this,最好不要过度使用refs
并且提升状态可能会有所帮助,如描述here

这是我的例子:

class Modal extends React.Component {
    constructor(props) {
        super(props);
        this.state = {show: props.show};
    }
    componentDidUpdate(prevProps, prevState) {
        let modal = document.getElementById('modal');
        if (prevProps.show) {
            modal.classList.remove('hidden');
        } else {
            modal.className += ' hidden';
        }
    }
    render() {
        return (
            <div id="modal" className={this.state.show ? '' : 'hidden'}>
                My modal content.
            </div>
        );
    }
}
class App extends React.Component {
    constructor(props) {
        super(props);
        this.state = {show: false};
        this.handleClick = this.handleClick.bind(this);
    }
    handleClick() {
        this.setState(prevState => ({
            show: !prevState.show
        }));
    }
    render() {
        return (
            <div>
                <button onClick={this.handleClick}>
                    Launch modal
                </button>
                <Modal show={this.state.show} />
            </div>
        );
    }
}
ReactDOM.render(<App />, document.getElementById('root'));

在这里,我不假装最终的真相,但试着提供另一种选择,以达到预期的效果。

答案 1 :(得分:1)

要做你需要的事情你根本不需要使用refs。您可以将状态作为prop传递给子组件。当状态更新时,prop会自动更新。然后,您可以使用此prop来切换类。您可以在jsbin here

上查看该操作
const Modal = (props) => {
  return (
    <div className={props.show ? 'show' : 'hide'}>modal</div>
  )
}

const styles = {
    main__title: 'main__title',
    addtask: 'addtask'
}

class App extends React.Component {
   constructor(props) {
      super(props);
      this.state = {show: false};
      this.toggleModal = this.toggleModal.bind(this);
   }

   render() {
       return (
           <div>
              <h2 className={styles.main__title}>Helloooo!</h2>
              <Modal show={this.state.show} /> 
              <button onClick={this.toggleModal} className={styles.addtask}>&#x2795;</button>
           </div>
       );
   }

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

}
ReactDOM.render(<App />, document.getElementById('root'));