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>
);
};
CodePudding user response:
To explain why your code isn't working:
useEffect(() => {
setIsShow(isBoolean);
}, [isBoolean, setIsShow]);
- initially when you set
isBooleanto true in parent, thisuseEffectin child runs too - Then you set
isShowto false from the child component - Then again you set
isBooleanto true in the parent component, but for theuseEffectabove, theisBooleanis 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>
);
};
