简体   繁体   中英

Implement hide/show in React 16

I'm trying to implement hide/show button in react 16 If I click a button then it should show Card button , if i click card button it should hide card button, I have implemented this but I have used componentwillReceiveprops props which is not recommended in react 16 I tried static getDerivedStateFromProps but it gets called when I do setState in handleclick working js fiddle

how can i achieve the same result without using componentwillReceiveprops

below is my code

class Test extends React.Component {

  state ={
      show: false
  }

  show(){
      this.setState({show: true})
  }



  render() {
      return (
          <div className="App">
              <button onClick={this.show.bind(this)}>show the button</button>
              {this.state.show && <Notification show={true}/>}
          </div>
      )
  }
}



  const style = {
      marginBottom: '0.5rem',
      float: 'right',
      boxShadow: '0 4px 8px 0 rgba(0, 0, 0, 0.1)',
      marginTop: '-9px'
  };



 class Notification extends React.Component {

    constructor(props){
        super(props);
        this.state ={
            open: true
        }
    }

    componentWillReceiveProps(props){
        console.log('will recieve props')
        this.setState({open: props.show})
    }


    handleClick(){
        this.setState({open: false})
    }

    render(){
        if(!this.state.open){
            return null
        }

      return (
          <div className="test">
              <div>
                  <button onClick={()=>this.handleClick()}>Card</button>
              </div>
          </div>
      )
  }

};




 ReactDOM.render(
     <Test name="World" />,
     document.getElementById('container')
 ); 

Instead of making it complicated, keep it simple and use toggleShow on the parent component and only mount Notification if show is true, pass in toggleShow from the parent as props to be able to toggle it from our child component

class Test extends React.Component {
  constructor() {
    super();
    this.state = { show: false };
    this.toggleShow = this.toggleShow.bind(this);
  }

  toggleShow() {
    this.setState(prevState => ({ show: !prevState.show }));
  }

  render() {
    return (
      <div className="App">
        <button onClick={this.toggleShow}>show the button</button>
        {this.state.show && <Notification hideNotification={this.toggleShow} />}
      </div>
    );
  }
}

const Notification = ({ hideNotification }) => (
  <div className="test">
    <div>
      <button onClick={hideNotification}>Card</button>
    </div>
  </div>
);

This is one of those cases where using hooks will make the syntax really terse:

import React, { useState } from "react";
import ReactDOM from "react-dom";

const Test = () => {
  const [show, setShow] = useState(false)

  return (
    <div className="App">
      <button onClick={() => { setShow(true) }}>show the button</button>
      {
        show &&
        <Notification handleClick={() => { setShow(false) }}/>
      }
   </div>
  )
}

const Notification = ({handleClick}) => (
   <div className="test">
      <div>
         <button onClick={handleClick}>Card</button>
      </div>
   </div>
)

But the substance is similar to https://stackoverflow.com/a/55673710/2417031 .

I am writing two solutions one that uses "open state and getDerivedStateFromProps lifecycle method" and another one that doesn't use "open state and getDerivedStateFromProps lifecycle method".

Solution 1(With open state and getDerivedStateFromProps):

class Test extends Component {
  state ={
      show: false
  }

  constructor(props) {
    super(props);
    this.closeShow = this.closeShow.bind(this);
  }

  show(){
      this.setState({show: true})
  }



  render() {
      return (
          <div className="App">
              <button onClick={this.show.bind(this)}>show the button</button>
              {this.state.show && <Notification show={true} onClose={this.closeShow}  />}
          </div>
      )
  }

  closeShow(e) {
    e.preventDefault();
    this.setState({show:false});
  }
}

and Notification Component as:

class Notification extends Component {
  constructor(props){
        super(props);
        this.state ={
            open: true
        }
    }

    static getDerivedStateFromProps(nextProps, prevState){
        if (nextProps.show !== prevState.open) {
          return {open: nextProps.show};
        }
        return null;

    }

    render(){
        const {onClose} = this.props;
        if(!this.state.open){
            return null
        }

      return (
          <div className="test">
              <div>
                  <button onClick={onClose}>Card</button>
              </div>
          </div>
      )
  }

}

Solution 2(Without open state and getDerivedStateFromProps)

Only Notification component requires change as shown:

class Notification extends Component {


    render(){
        const {show, onClose} = this.props;
        if(!show){
            return null
        }

      return (
          <div className="test">
              <div>
                  <button onClick={onClose}>Card</button>
              </div>
          </div>
      )
  }

}

With Solution 2 we can use the stateless component as there is no state to manage and stateless components render fastly as compare to stateful components. Code for the stateless component is as:

const Notification = function(props) {

        const {show, onClose} = props;
        if(!show){
            return null
        }

      return (
          <div className="test">
              <div>
                  <button onClick={onClose}>Card</button>
              </div>
          </div>
      )
}

It is better to follow the 2nd solution as, when the show state of click button is managed from the Test component's "show" state variable then the hide state of the click button must also be managed from the Test component's "show" state variable.

I have given solution 1 just to have an understanding of getDerivedStateFromProps lifecycle method.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM