I made a component for one Button with animation effect so that i can use it in my other components by simply importing it. I did a lot of code in Button component for animation so i don't want to use a lot of same code again and again in other components.
Is there any way I can use the Button for different events by just importing. For example; In one component I import the Button as submitting the user information and in other component i am import the Button for displaying user data.
Of course! This is the components idea. You mught want to receive a prop in your Button to handle whatever happens onClick.
I.E.
Parent Component
create the especific function to handle
function handleClick() { ... }
<YourCustomButton onClick={handleClick} />
In YourCustomButton just use this function on event
class YourCustomButton extends React......
<Button onClick={this.props.onClick}> ...
Create a props for button to provide an option like
Implement in other component:
<custombutton mode={"submitmode"} clickevent={handleBtnClick} />
<custombutton mode={"displaymode"} clickevent={handleBtnClick} />
handleBtnClick=() =>{
if(mode =="submitmode"){
//..do code for submit
}
else if(mode=="displaymode"){
//..do code for display
}
}
Actual button component:
class Button extends custombutton{
handleClick =() =>{
this.props.clickevent();
}
render(){
return(
{props.mode=="submitmode" &&
<button type="submit" onClick={handleClick} class="submitstyle" />
}
{props.mode=="displaymode" &&
<button class="displaystyle" onClick={handleClick} />
}
);
}
}
Of course there is, just give it different props:
Example on codesandbox:
https://codesandbox.io/s/admiring-wing-okiqw
The parent:
function App() {
return (
<div className="App">
<h1>Hi there</h1>
<h2>Click on first button to sum 1, click to second button to sum 2!</h2>
<Fbutton functionality="sumone" />
<Fbutton functionality="sumtwo" />
</div>
);
}
You are calling Fbutton two times, one with sumone another with sumtwo props.
The son:
function Fbutton(props) {
const [count, setCount] = useState(0);
const sumone = () => setCount(count + 1);
const sumtwo = () => setCount(count + 2);
return (
<div>
<button onClick={props.functionality === "sumone" ? sumone : sumtwo}>
Sum: {count}
</button>
</div>
);
}
suppose you have a button like <Button pageName="home" />
And in that component suppose ,
class Button extends Compoenent {
onClick =()=>{
if(this.props.pageName == "home"){
// do your home action
} else if(this.props.pageName == "tab"){
// do your tab action
}
}
render(){
return(
<Button onClick={() => this.onClick()} />
)
}
}
Hope thats clear, feel free for doubts
Related
I have the following Button component and the main file.
I want to be able to set "onclick" on the main file while keeping the original onclick behavior.
So in the following example, by clicking the button for now it does console.log "animated." only, but the desired result is "animated." and "clicked". (or vice versa)
Is it possible? Thanks.
// Button.jsx
export default function Button(props) {
function animate(e) {
console.log("animated.");
//
}
return (
<button
{...props}
ref={button}
onClick={e => {
animate(e);
}}
>
{props.children}
</button>
);
}
// main.js
import Button from "./Button.jsx"
..
<Button onClick={(e) => console.log("clicked.")}>
Text
</Button>
You can simply call the onClick from the props so that both gets executed.
export default function Button(props) {
function animate(e) {
console.log("animated.");
//
}
return (
<button
{...props}
ref={button}
onClick={e => {
animate(e);
if(props.onClick) props.onClick(e);
}}
>
{props.children}
</button>
);
}
Edit: as suggested in comment, you can also use Optional chaining (?.) instead of if statement.
I'm trying to render JSX when a material-ui button is clicked. I'm logging to the console when clicking but cannot see any of the JSX getting rendered.
interface TileProps {
address?: string;
}
const renderDisplayer = (address: string) => {
console.log('Rendering address', address!);
if (typeof(address) == 'undefined' || address == '') {
return(<div className='error'><li>No address found</li></div>)
}
return(<AddressDisplayer address={address} />)
}
const Tile = (props: TileProps) => {
return(
<div className='tile'>
<ul>
<li>{props.address}</li>
</ul>
<Button variant='contained' onClick={() => {renderDisplayer(props.address)}}>Display</Button>
</div>
)
}
export default Tile;
I can see the console.log('Rendering address', address!); running when the button is clicked, but the JSX isn't getting rendered.
Could this be because I'm using React functional components instead of class components?
Your question is somehow unclear for me. If you want to render <div className='error'><li>No address found</li></div> based on typeof(address) == 'undefined' || address == '' condition, there is no need to click on the button and it's better to use conditional rendering. For example:
{!props.address ? (
<div className='error'><li>No address found</li></div>
) : (
<AddressDisplayer address={props.address} />
)}
But if you want to render your address component by clicking on the button, you should define a state and set it true when clicking on the button. Like this:
const [shouldShowAddress, setShouldShowAddress] = useState(false);
{shouldShowAddress && (
<>
{!props.address ? (
<div className="error">
<li>No address found</li>
</div>
) : (
<AddressDisplayer address={props.address} />
)}
</>
)}
<Button
variant="contained"
onClick={() => {
setShouldShowAddress(true)
}}
>
Display
</Button>
Please read about the Life cycle This not how react work onclick function
renderDisplayer is called and return JSX to onClick event you need to use state here to render the component with ternary oprator renderDisplayer fuction do setState so DOM will update
I have a toggle button that show and hides text. When the button is clicked I want it to hide another component and if clicked again it shows it.
I have created a repl here:
https://repl.it/repls/DapperExtrasmallOpposites
I want to keep the original show / hide text but I also want to hide an additional component when the button is clicked.
How to I pass that state or how do I create an if statement / ternary operator to test if it is in show or hide state.
All makes sense in the repl above!
To accomplish this you should take the state a bit higher. It would be possible to propagate the state changes from the toggle component to the parent and then use it in any way, but this would not be the preferred way to go.
If you put the state in the parent component you can use pass it via props to the needed components.
import React from "react";
export default function App() {
// Keep the state at this level and pass it down as needed.
const [isVisible, setIsVisible] = React.useState(false);
const toggleVisibility = () => setIsVisible(!isVisible);
return (
<div className="App">
<Toggle isVisible={isVisible} toggleVisibility={toggleVisibility} />
{isVisible && <NewComponent />}
</div>
);
}
class Toggle extends React.Component {
render() {
return (
<div>
<button onClick={this.props.toggleVisibility}>
{this.props.isVisible ? "Hide details" : "Show details"}
</button>
{this.props.isVisible && (
<div>
<p>
When the button is click I do want this component or text to be
shown - so my question is how do I hide the component
</p>
</div>
)}
</div>
);
}
}
class NewComponent extends React.Component {
render() {
return (
<div>
<p>When the button below (which is in another component) is clicked, I want this component to be hidden - but how do I pass the state to say - this is clicked so hide</p>
</div>
)
}
}
I just looked at your REPL.
You need to have the visibility state in your App component, and then pass down a function to update it to the Toggle component.
Then it would be easy to conditionally render the NewComponent component, like this:
render() {
return (
<div className="App">
{this.state.visibility && <NewComponent />}
<Toggle setVisibility={this.setVisibility.bind(this)} />
</div>
);
}
where the setVisibility function is a function that updates the visibility state.
I am trying to implement a collapsible component. I have designed it such as, on click of a button, a block of dynamic text will appear. I made a functional component and using the tags in a class. The name of the component is, CustomAccordion.jsx and using this component in Container.jsx
I have tried to create a button and a function for onClick event.
Part of the CustonAccordion.jsx
const handleToggle = () : string =>{
let content = this.nextElementSibling;
if (content.style.maxHeight){
content.style.maxHeight = null;
}else{
content.style.maxHeight = content.scrollHeight +'px';
}
}
export default function CustomAccordion(props: PropType): React.Component<*> {
const { title, children } = props
return(
<div>
<AccordionButton onClick={() => this.handleToggle()}>{title}</AccordionButton>
<AccordionContent>
<p>{children}
</p>
</AccordionContent>
</div>
)
}
Part of calling Container.jsx
<CustomAccordion title = {this.props.name}>
<p>This is the text passed to component.</p>
</CustomAccordion>
<br />
This does not show the expanded text and it seems that the click event does not work properly. I am very new in react, guessing the syntax might be incorrect.
In react you should generally try to avoid touching DOM directly unless you really have to.
Also you are accessing the handleToggle function wrongly. It should be onClick={() => handleToggle()} because this in your case is window/null and so it has no handleToggle method.
Instead you can use a stateful class component to achieve the same thing.
export default class CustomAccordion extends React.Component {
state = {show: false};
toggle = () => this.setState({show: !this.state.show});
render() {
const {title, children} = this.props;
const {show} = this.state;
return (
<div>
<AccordionButton onClick={this.toggle}>{title}</AccordionButton>
{show && (
<AccordionContent>
<p>{children}</p>
</AccordionContent>
)}
</div>
)
}
}
If you want to have some kind of animation, you can set different className based on the show state instead of adding/removing the elements.
I am trying to change the background color of a page to one of three colors, each with a respective button. The buttons onClick function is supposed to call a function to change the color, but for some reason it is not working and instead the last button is setting the background color of the page when first loaded. Why is this? The below code is not working.
class Game extends React.Component
{
setBgColor(bgColor)
{
document.body.style.backgroundColor = bgColor;
}
render()
{
return(
<div id = "buttonWrapper">
<button id = "redButton" onClick = {this.setBgColor("red")}>RED</button>
<button id = "greenButton" onClick = {this.setBgColor("green")}>GREEN</button>
<button id = "blueButton" onClick = {this.setBgColor("blue")}>BLUE</button>
</div>
);
}
Thank you in advance.
#Mickael-conner, please use the following code for defining functions for your onClick events:
class Game extends React.Component
{
setBgColor(bgColor)
{
document.body.style.backgroundColor = bgColor;
}
render()
{
return(
<div id="buttonWrapper">
<button id="redButton" onClick={() => this.setBgColor("red")}>RED</button>
<button id="greenButton" onClick={() => this.setBgColor("green")}>GREEN</button>
<button id="blueButton" onClick={() => this.setBgColor("blue")}>BLUE</button>
</div>
);
}
The following article has explained different ways for defining functions inside React components:
5 Approaches for Handling this