So basically I want when I press on the Button I want to Icon to disappear as well as Button. I have tried something but clearly, it is not working, so I would appreciate some help if possible
const Button = (props) => {
const[toggleIcon, setToggleIcon]=React.useState('true')
function Icon() {
toggleIcon(false)
}
return(
<div>
<button onClick={()=> setToggleIcon('false')}></button>
</div>
)
}
export default Button
const Icon = (props) => {
return(
<div>
<Icon>{props.Icon('false')}</Icon>
</div>
export default Icon
You can prevent a component from rendering by returning null. Use conditional rendering with the toggleIcon state as the condition. The onClick handler changes the state.
E.G.:
const Button = () => {
const [toggleIcon, setToggleIcon] = React.useState(true)
return toggleIcon ? (
<button onClick={() => setToggleIcon(false)}><Icon /></button>
) : null
}
export default Button
Take a look at the Conditional Rendering section of the React docs.
Related
For example I have this code.
And I want to use CSS transitionfor Button when showButton and when !showButton. Now it's just removed and add Button when showButton changes.
{showButton && (
<Button
onClick={() => setShowMessage(true)}
size="lg"
>
Show Message
</Button>
)}
Is it possible make by some events or appending classNames like active?
Append the className with the ternary operator.
But, for example, this code will only adjust the class of the button specified (effectively doing the same thing you described, hiding & showing the button):
import React, { useState } from 'react';
export const Component = () => {
const [showButton, setShowButton] = useState(false);
const handleClick = () => {
setShowButton(true);
}
return (
<button
onClick={handleClick}
className={showButton ? 'showButtonClass' : 'hideButtonClass'}
>
Show Message
</button>
);
};
For content to show once the button is clicked, you'll need something like:
import React, { useState } from 'react';
export const Component = () => {
const [showMessage, setShowMessage] = useState(false);
const handleClick = () => {
setShowMessage(true);
}
return (
<div>
<button
onClick={handleClick}
>
Show Message
</button>
{showMessage && <h1>
The message you'll see when clicking!
</h1>}
</div>
);
};
Am trying to render a new component onclick a button in react js. Am using functional components and I can't handle it. Eg: am in the UserManagement component and on a button click I need to render another component named employee management.
You can conditionally render your component.
Example :
EmployeeManagement.js
const EmployeeManagement = () => {
....
return (
<div>
EmployeeManagement
</div>
);
}
UserManagement.js
const UserManagement = () => {
const [hasRender, setRender] = useState(false);
const onShow = React.useCallback(() => setRender(true), []);
return (
<>
<button onClick={onShow}>Show Employee Management</button>
{hasRender && <EmployeeManagement />}
</>
)
}
One way to do this would be to add a local state in UserManagement,
that holds a boolean value indication whether the component should be hidden or shown.
Then you will have something like:
function UserManagement() {
const [compIsShown, setCompIsShown] = useState(false);
return (
// Whatever else you're rendering.
<button onClick={() => setCompIsShown(true)}>...</button>
{compIsShown && <OtherComp />}
)
}
What will happen is that compIsShown will initialize as false,
so this condition compIsShown && <OtherComp /> will prevent it from rendering.
Then, when you click the button, the state will set, causing a re-render, except now the condition will be true, so <OtherComp> will be rendered.
There are other ways to go about this.
Depends mostly on the use-case.
use a visible state & toggle it in onClick:
const [visible, setVisible] = useState(false)
onClick = () => {setVisible(true)}
then render it like this:
{visible && <EmployeeManagement onClick={onClick} />}
This is the function where I am passing the onClick prop (setShowModal is setState() from the useState hook):
<MyFunctionalComponent
onClick={() => setShowModal(true)}
...other props here
/>
This is the functional component that receives the prop:
export const MyFunctionalComponent = ({ onClick }) => {
return (
<section>
...other code here
{onClick && (<Button>{ctaText}</Button>)}
</section>
);
};
But the Button component never appears, because the prop onClick is undefined. When I console.log the prop inside the functional component, it initially prints the function in the console, but then prints two more times as undefined. Could someone explain why that would be? I got it to work by spreading ...props instead. But the console.log remains the same? I don't understand why. This is my first question on Stack Overflow, so feel free to give me feedback on how to ask better questions :)
The reason why you are receiving an 'undefined' response is because as #Zrogua mentioned, onClick is an event listener function rather than a persistent value (like state you define).
import React from "react";
const YourButton = ({ onClick }) => {
console.log(onClick);
return <section>{onClick && <button>here</button>}</section>;
};
const ParentDiv = () => {
return (
<div>
<h1>Button Props</h1>
<h2>Start editing to see some magic happen!</h2>
<YourButton onClick={() => console.log("CLICK")} />
</div>
);
};
export default ParentDiv;
Result of console.log():
function onClick() // index.js:27:25
The reason why this is because props are read-only. From the React Docs:
Whether you declare a component as a function or a class, it must never modify its own props ... Such functions are called “pure” because they do not attempt to change their inputs, and always return the same result for the same inputs.
Therefore your button will only show if the onClick function is defined. For example, if you did not give onClick a function or value, the button will not appear:
import React, { useState } from "react";
const YourButton = ({ onClick }) => {
console.log(onClick);
return (
<section>
{onClick && <button>This button is shown if a button is defined.</button>}
</section>
);
};
const ParentDiv = () => {
return (
<div>
<h1>Button Props</h1>
<YourButton onClick={() => console.log("CLICK")} />
<YourButton /> {/* You won't see this button because the function is not defined. */}
</div>
);
};
export default ParentDiv;
The button appears because the prop has a value that is not undefined (your onClick function), and because it is read-only, you cannot access that function in your child component.
Instead, (1) define the modal state in the parent component and (2) pass the state through props to the button like so:
import React, { useState } from "react";
const YourButton = ({ onClick }) => {
console.log(onClick);
return (
<section>
{onClick && <button>This button is shown if a button is defined.</button>}
</section>
);
};
const AltButton = ({ modal }) => {
return (
<section>
{modal && (
<button>This button is shown the modal state is passed.</button>
)}
</section>
);
};
const ParentDiv = () => {
const [modal, setModal] = useState(false);
return (
<div>
<h1>Button Props</h1>
<YourButton onClick={() => console.log("CLICK")} />
<YourButton />{" "}
{/* You won't see this button because the function is not defined. */}
<section>
<button onClick={() => setModal(!modal)}>OPEN MODAL</button>
</section>
{modal && <p>this is dependent on state</p>}
<AltButton modal={modal} />
</div>
);
};
export default ParentDiv;
Working CodeSandbox: https://codesandbox.io/s/stack-66715327-passingfunctions-92pzr
Finally, if I am reading between the lines and understanding correctly that you are looking to hide a button when a modal is open, here is a little modal wrapper trick I use for buttons that open modals: https://codesandbox.io/s/stack-66715327-modalwrapper-wvl54
You can't pass onClick, onClick is just an event listener. You should pass the state
<MyFunctionalComponent onClick={() => setShowModal(!showModal)}
showModal={showModal}
...other props here />
/>
export const MyFunctionalComponent = ({ showModal }) => {
return (
<section>
...other code here
{showModal && (<Button>{ctaText}</Button>)}
</section>
);
};
I believe this should work. Let me know if this is what you were looking for.
I think that rather then passing callback you should pass variable which decide if component should show or not. Check this example.
export const MyFunctionalComponent = ({ isShow, onClick }) => {
return (
<section>
...other code here
{isShow && <div>something</div>}
</section>
);
};
export default function App() {
const [showModal, setShowModal] = useState(false);
return (
<MyFunctionalComponent
isShow={showModal}
onClick={() => setShowModal(true)}
/>
);
}
I also suppose that you can make mistake and have something other on mind .. like this:
<section>
...other code here
<button onClick={ onClick }>something</button>}
</section>
I am working with a form in react, and what I would like is that when I click a button, I add a new component which is just an input to the screen. It all mostly works, as planned. The issue is with the following: the layout is that I have one main component, which then displays a child component. That child component is called from a map of a useState. (More after code snippet)
This is the code of the main component:
import React, { useState } from "react";
import SingleProfile from "./individual_profile";
const ProfileInformation = (props) => {
console.log("proflie render");
const [ProfilesBoolean, setProfilesBoolean] = useState(false);
const [profiles, setProfiles] = useState(props.Data['profiles'])
const FieldAdd = (event)=>{
event.preventDefault();
const copy = profiles;
copy.push({Network:'',url:''})
return(copy)
}
function CreateInput(){
return profiles.map((data, index) =><SingleProfile index={index} data={data} />)
}
const accordion = (event) => {
const NextElement = event.target.nextElementSibling;
if (!event.target.className.includes("display")) {
NextElement.style.maxHeight = NextElement.scrollHeight + "px";
} else {
NextElement.style.maxHeight = 0;
}
};
return (
<div className="AccordionItem">
<div
className={
ProfilesBoolean ? "AccordionHeader-display" : "AccordionHeader"
}
onClick={(e) => setProfilesBoolean(!ProfilesBoolean)}
id="ProfileForm"
>
Profiles
</div>
<div className="AccordionContent">
<div className="AccordionBody">
{
profiles.map((data, index) => (
<SingleProfile index={index} data={data} />
))
}
<button id="ProfileAdd" onClick={(e) => {setProfiles(FieldAdd(e))}}>
Add a profile
</button>
</div>
</div>
</div>
);
};
export default ProfileInformation;
When I click the button and onClick fires FieldAdd() the useState updates, with a new empty object as expected. However, it does not appear inside my <div className="AccordionBody"> as I would expect it to.
The following code is used to display components, by opening and closing the child div. When it is open is when you see the child components and the add button. If I click the div, to close and then click again to re-open it, the new child component appears.
<div
className={ProfilesBoolean ? "AccordionHeader-display" : "AccordionHeader"}
onClick={(e) => setProfilesBoolean(!ProfilesBoolean)}
id="ProfileForm"
>
Profiles
</div>;
Is it possible to have the child component appear without having to close and re-open the div?
Your clickHandler FieldAdd is incorrect. You are mutating the state directly which will not cause re-render.
use setProfiles to update the state in the clickHandler. Like this
const FieldAdd = (event)=>{
setProfiles(prev => [...prev, {Network:'',url:''}])
}
Trigger the onClick like this
<button id="ProfileAdd" onClick={(e) => {FieldAdd(e)}}>
Add a profile
</button>
...
I have a Dropdown made with React Hooks. The button should have Arrow, which rotate. My first Version works fine:
const DropdownMenu= (props) => {
const [open, setOpen] = useState(false);
const openDropdown = (): void => setOpen(prevState => !prevState);
return (
<div>
<Button
onClick={openDropdown}
dropdownIsOpen={open}
>
Text </Button>
<DropdownContent isOpen={isOpen} />
</div>
);
};
export default DropdownMenu;
const Button = (props) => {
return (
<Button Click={props.onClick}>
Text
<Arrow rotate={props.dropdownIsOpen} color={designTheme.color.primary} />
</Button>
);
};
export default Button;
But now I have multiple Dropdowns and want to use them with the same component. I gave the toggleNode as prop. Now the Arrow rotate but without the transition:
const DropdownButton = (props) => {
const [isOpen, setOpen] = useState(false);
const onToggle = (): void => setOpen(prevState => !prevState);
return (
<Dropdown
isOpen={props.isOpen}
onToggle={onToggle}
toggleNode={
<Button dropdownIsOpen={isOpen}>
Text
</Button>
}
/>
);
};
export default DropdownButton;
Have someboy an idea?
Thank you!
my guess is, you are exporting different Button
How can you use Button inside Button, possibly by importing Button from somewhere else. And then you are again exporting Button. This will be confuse for transpiler, as which Button to be exported.
You might want to rename your custom Button to something else
const Button = (props) => {
return (
<Button Click={props.onClick}>
Text
<Arrow rotate={props.dropdownIsOpen} color={designTheme.color.primary} />
</Button>
);
};
export default Button;
Given your Button component takes an onClick prop:
const Button = (props) => {
return (
<Button Click={props.onClick}>
Text
<Arrow rotate={props.dropdownIsOpen} color={designTheme.color.primary} />
</Button>
);
};
NOTE: As #SagarMore points out, there my also be a naming collision between some imported Button component and your Button component.
You may just need to pass a callback to Click (terrible name, BTW, should be onClick, hopefully it was just a typo):
const DropdownButton = (props) => {
const [isOpen, setOpen] = useState(false);
const onToggle = (): void => setOpen(prevState => !prevState);
return (
<Dropdown
isOpen={props.isOpen}
onToggle={onToggle}
toggleNode={
<Button onClick={onToggle} dropdownIsOpen={isOpen}>
Text
</Button>
}
/>
);
};
Passing onToggle to the inner button's onClick handler should now toggle the isOpen state of the DropDown.
This was my fault.
In my Dropdown component I render two different states conditional. So it renders the start or the end state and don't use the animation. I have to render a animation and don't render new when I click so the animation works.