Reputation: 337
I have this structure
component 1
import React, { useState } from 'react'
export default function Component1() {
return (
<div>
<button onClick={handleChange}></button>
</div>
)
}
component 2
import React, { useState } from 'react'
export default function Component2() {
return (
<div>
<button onClick={handleChange}></button>
</div>
)
}
and the parent
import React from 'react'
export default function Parent() {
return (
<div>
<Component1 />
<Component2 />
</div>
)
}
The question is, how can I toggle visibility between the two, without having a button in the parent. Just the buttons inside each component. - The Component1 should be visible by default and when you press the button in Component1 it will hide it and show Component2 and vice-versa.
I've tried using useState hook on the Component1 button, but I'm not sure how to export the state and add it to the parent component.
const [showMini, setShowMini] = useState(false);
const handleChange = () => {
setShowMini(true);
}
Is this possible? or it's possible just with a button in the parent that control the two? Thanks
Upvotes: 2
Views: 2359
Reputation: 1548
Try this:
import React from 'react'
export default function Parent() {
const[show,setShow]=useState(false);
const handleChange=()=>{
setShow(!show);
}
return (
<div>
{show ? <Component2 handleChange={handleChange}/> : <Component1 handleChange={handleChange}/>}
</div>
)
}
and inside Component1 have this:
import React, { useState } from 'react'
export default function Component1({handleChange}) {
return (
<div>
<button onClick={handleChange}></button>
</div>
)
}
Similarly do it for Component2
Upvotes: 3
Reputation: 47
Try this. You can send information from child to parent with functions passed as a prop.
Parent Component:
const Parent = () => {
const [show, setShow] = useState(true);
const toggleVisibility = () => {
setShow(!show);
};
return (
<div>
{show ? (
<Child1 toggle={toggleVisibility}></Child1>
) : (
<Child2 toggle={toggleVisibility}></Child2>
)}
</div>
);
};
Child 1
const Child1 = (props) => {
const { toggle } = props;
return (
<div style={{ width: '100px', height: '100px' }}>
<button onClick={toggle}>Child 1's button</button>
</div>
);
};
Child 2
const Child2 = (props) => {
const { toggle } = props;
return (
<div style={{ width: '100px', height: '100px' }}>
<button onClick={toggle}>Child 2's button</button>
</div>
);
};
Upvotes: 0
Reputation: 2254
Your parent component should keep track of the state:
import React, {useState} from 'react'
export default function Parent() {
const [showChild, setShowChild] = useState(1);
const showNextChild = () => {
setShowChild( showChild === 1 ? 2 : 1 ); // set to 2 if already 1, else to 1
}
return (
<div>
{ showChild === 1 && <Component1 handleChange={showNextChild} /> }
{ showChild === 2 && <Component2 handleChange={showNextChild} /> }
</div>
)
}
A few notes:
Your components are identical, so the duplication is unnecessary, but I assume the example is just contrived.
This assumes toggling 2 components back and forth. If you have more than 2 components you are "looping" through, you can instead increment the previous showChild
state and then reset it to 0 if higher than the # of components you have.
The syntax you see, showChild === 1 && <Component1 ...
uses the behavior of the &&
operator which actually returns the 2nd item it is evaluating if both are true. In other words, const isTrue = foo && bar;
sets isTrue
to bar
, not true
as you might expect. (You know, however, that bar is "truthy" in this case, so isTrue
still works in future if
statements and such.) The component is always truthy, so the effect is that the component is returned if the first part is true, otherwise it is not. It's a good trick for conditionally showing components.
Upvotes: 0
Reputation: 66
You can manage the state in the parent and pass down a handler to the children
import React, { useState } from 'react'
const [currentView, setCurrentView] = useState('component1')
const changeCurrentView = (view) => setCurrentView(view)
const renderViews = () => {
switch(currentView) {
case 'component1':
return <Component1 changeCurrentView={changeCurrentView} />
case 'component2':
return <Component2 changeCurrentView={changeCurrentView} />
default:
return <Component1 changeCurrentView={changeCurrentView} />
}
}
export default function Parent() {
return (
<div>
{renderViews()}
</div>
)
}
Other components
import React from 'react'
export default function Component1({ changeCurrentView }) {
return (
<div>
<button onClick={() => changeCurrentView('component1')}></button>
</div>
)
}
export default function Component2({ changeCurrentView }) {
return (
<div>
<button onClick={() => changeCurrentView('component2')}></button>
</div>
)
}
Upvotes: 0
Reputation: 1751
You can do with state value and pass handleChange function ad props in the child component and in click on the button in child component call handleChange method under parent component and show hide based on state value.
import React from 'react'
const [showChild, setshowChild] = useState(false);
const handleChange = () => {
setshowChild(!showChild);
}
export default function Parent() {
return (
<div>
{showChild ? <Component2 handleChange = {handleChange}/> : <Component1 handleChange= {handleChange} />}
</div>
)
}
Upvotes: 0