Search code examples
reactjsreact-hooksreact-functional-componenttsx

show - hide component with hook function works only one time


I am trying to show and hide a functional component, it's works only works on load. after hide it's not shows again. i understand that, the way i use the functional component in wrong way.

any one suggest me the correct way please?

here is my code : (index.tsx)

import React, { Component, useState } from 'react';
import { render } from 'react-dom';
import Hello from './Hello';
import './style.css';

const App = () => {
  const [isBoolean, setBoolean] = useState(false);

  const showComponent = () => {
    setBoolean(true);
  };

  return (
    <div>
      <Hello isBoolean={isBoolean} />
      <p>Start editing to see some magic happen :)</p>
      <button onClick={showComponent}>Show hello component</button>
    </div>
  );
};

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

Hello component:

import React, { useEffect, useState } from 'react';

export default ({ isBoolean }: { isBoolean: boolean }) => {
  const [isShow, setIsShow] = useState(false);

  useEffect(() => {
    setIsShow(isBoolean);
  }, [isBoolean, setIsShow]);

  const shufler = () => {
    setIsShow(false);
  };

  if (!isShow) {
    return null;
  }

  return (
    <div>
      <p>hi {JSON.stringify(isShow)}</p>
      <button onClick={shufler}>Hide Component</button>
    </div>
  );
};

Live Demo


Solution

  • No need to maintain a derived state from prop in child component(Hello), you can pass callback and state as props from parent component(index) to child.

    Cause of the Problem:

    After hiding the component isShow was set to false , isBoolean is still true. So the next time when we click the show button isBoolean hasn't changed, it's still true which will not trigger the useEffect in the Hello.tsx , isShow was never set to true which causes the child to return null.

    index.tsx

    import React, { Component, useState } from 'react';
    import { render } from 'react-dom';
    import Hello from './Hello';
    import './style.css';
    
    const App = () => {
      const [isBoolean, setBoolean] = useState(false);
    
      const showComponent = () => {
        setBoolean(true);
      };
    
      const hideComponent = () => {
        setBoolean(false);
      }
    
    
    
      return (
        <div>
          <Hello isBoolean={isBoolean} hideComponent={hideComponent} />
          <p>Start editing to see some magic happen :)</p>
          <button onClick={showComponent}>Show hello component</button>
        </div>
      );
    };
    
    render(<App />, document.getElementById('root'));
    

    Hello.tsx

     import React, { useEffect, useState } from 'react';
    
    export default ({ isBoolean, hideComponent }: { isBoolean: boolean }) => {
      if (!isBoolean) {
        return null;
      }
    
      return (
        <div>
          <p>hi {JSON.stringify(isBoolean)}</p>
          <button onClick={hideComponent}>Hide Component</button>
        </div>
      );
    };