Home > OS >  show - hide component with hook function works only one time
show - hide component with hook function works only one time

Time:01-21

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

CodePudding user response:

To explain why your code isn't working:

useEffect(() => {
    setIsShow(isBoolean);
}, [isBoolean, setIsShow]);
  • initially when you set isBoolean to true in parent, this useEffect in child runs too
  • Then you set isShow to false from the child component
  • Then again you set isBoolean to true in the parent component, but for the useEffect above, the isBoolean is true now, and it was true also in previous render, so it doesn't run anymore.

So if possible, no need to duplicate isBoolean state also in child, just pass it as props and use it directly, as in the other answer.

CodePudding user response:

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>
  );
};
  •  Tags:  
  • Related