How can i unmount a functional component from DOM on click of a Button - reactjs

I would like to "Unmount a simple Functional Component" from the DOM. I searched a lot and saw most of the tutorials are based on Class Components and I did'nt see any simple example on it. My requirement is Unmounting a Functional component from the DOM on click on a button. Following is the component with the button which i likes to unmount when click on it. Hopes someone can help me to do it. Thanks in Advance !
import React from 'react'
function App() {
return (
<div className='app-component'>
<h2 className="h2">App Component</h2>
<button>Unmount This Component</button>
</div>
)
}
export default App

If you want to unmount a component then you can use conditional rendering where you can declare state in parent component and based on the state you can mount or unmount component as:
This is the parent component from where you want to mount or unmount
CODESANDBOX DEMO
If you want to toggle component once then you can do the following because there is only one way to change state i.e from Test component. If you unmount this component there is no way to mount it again. So you can also declare button in App component from where you can mount or unmount on click of a button. CODESANDBOX
Parent component
export default function App() {
const [isShowing, setIsShowing] = useState(true); // STATE
return (
<div className="App">
{isShowing && <Test setIsShowing={setIsShowing} />}
</div>
);
}
Child component
function Test({ setIsShowing }) {
function unmountComponent() {
setIsShowing(false);
}
return (
<div className="app-component">
<h2 className="h2">App Component</h2>
<button onClick={unmountComponent}>Unmount This Component</button>
</div>
);
}

You can use state flag for removing element like this:
import React from 'react'
function App() {
const [flag,setFlage]=useState(true);
return (
<div className='app-component'>
{flag?<h2 className="h2">App Component</h2>:null}
<button onClick={()=>setFlag(!flage)} >Unmount This Component</button>
</div>
)
}
export default App

Related

In react functional component, stop child re-rendering when parent function is called from child component

in react I have 2 functional component, I want to call parent's function in child component on button click which update parent state. on this function invoke my child component is re-render.so I want Stop this re-rendering, i trying solve it as follow but not working
app.js
import React, { useState, useCallback } from "react";
import Child from "./child";
export default function App()
{ let [show, setShow] = useState(false);
console.log("App Re-render:", show);
const setMyState = useCallback(() => {
setShow(!show);
});
return (
<div className="App">
<h1>Parent Component</h1>
<h2>----------------------------------</h2>
<Child func={setMyState}></Child>
</div>
);
}
child.js
import React, { memo } from "react";
function Child({ func }) {
console.log("Child re-render");
return (
<div>
<p>Child Component</p>
<button onClick={func}>Call Parent Method </button>
</div>
);
}
export default memo(Child);
this "func" function should call multiple time.
please help me to solve this problem
The code you posted looks good. Do you have more code that isn't posted? Can you try to reproduce in an example?
You don't need the useCallback hook to do the functionality you are looking for. So skip that.
I have done the same thing here and it works:
https://codesandbox.io/s/gallant-hellman-60lw3d?file=/src/App.js

React tailwind, cannot pass tailwind css from parent to child

I am running into a simple issue that doesn't seem to have an answer on quick google search or Tailwind doc.
I am a Vuejs user but I have started learning React. I have opted to use TailwindCSS for testing my React application but I noticed there is some differences of Tailwind usage between Vuejs and React.
In Vue, I can control a child component via the parent component like so:
Parent component:
<template>
<div class="w-screen">
<ChildComponent class="w-1/2 mx-auto" />
</div>
</template>
With the child being able to centre on screen through the above parent component as should in the ChildComponent's class.
However, when I tried to do the same in React like so:
Parent component:
import Homepage from './views/Homepage';
function App() {
return (
<div className='bg-black w-screen'>
<Homepage className="w-1/2 mx-auto"/>
</div>
);
}
export default App;
Nothin happens when I placed the CSS at the Homepage child component from the parent.
I am sure there is a simple answer but I wasn't about to search the doc or use any keywords to find this problem. Anyone got a hint or confirm this is intended in React or have I done something wrong with the installation?
This is less of a Tailwind question and more of a React question. You cannot use className on the Homepage component without passing it as a prop. In your case, Homepage is not expecting any className. So while making your Homepage component you have to provide a prop called 'className' then it will work fine.
Or if you simply use a div in place of Homepage it will work normally. Have a look at this codesandbox link
You need to consider that <Homepage/> is a React component and cannot accept HTMLAttrs just like that.
this example might clear it:
const app = () => {
<div className="bg-black">
<Homepage className="bg-red" />
</div>
}
const homePage = (props) => {
<div className={props.className}>
<h1 className="bg-red">hi</h1>
</div>
}
the className that you pass to <Homepage/> is actually a props rather than Html attribure.
In Vue it's fairly straightforward but in react you need to be explicit and use className in your component
// Creating component
const Button = ({ className, children }) => {
return <button className={`${className} bg-red-500`}>{children}</button>
}
export default Button
// Using component
<Button className="text-white">MyButton</Button>
import Homepage from './views/Homepage';
function App() {
return (
<div className='bg-black w-screen'>
<Homepage className="w-1/2 mx-auto"/>
</div>
);
}
export default App;
views/Homepage
you have to receive props that are going to be passed as className
const homePage = ({className}) => {
<div className={className}>
<h1 className="bg-red">hi</h1>
</div>
}
export default homePage
then export your component

onClick not working in form element in react, but works in button?

Trying to get an onClick function working in react with a form , however, it isnt working but using a button does.
The following code works with the button but not the input. I'm wondering what I might be
<CustomInput
onChange={(v) => setLastName(v)}
label="Last Name*"
invalid={
(lastName || validate) &&
!yup.string().required().isValidSync(lastName)
}
value={lastName}
onClick={() => alert('hello')}
/>
<button onClick={() => alert('hello')}>Click me!</button>
This is probably happening because you didn't use the onClick prop anywhere inside CustomComponent. When you passed the onClick prop to the button, React knows that it has to create a button and attach an onclick event listener to it which fires off your alert when the button is clicked. However, when you pass the onClick prop to CustomComponent, since React innately doesn't know what CustomComponent is, it doesn't create a component immediately. It first accesses your CustomComponent's source file, and creates DOM elements according to CustomComponent's render method's return.
Any props that were passed to CustomComponent can be accessed it. When passing props in this manner, React assumes that onClick is just another name for a prop, and doesn't understand that you want it to attach an eventListener to the wrapper element in the return statement of CustomComponent's render method. You will have to manually attach this inside CustomComponent.
for example,
CustomButton.js
import React from 'react';
const CustomButton = props => {
return (
<div>
<button>Click me</button>
</div>
);
};
export default CustomButton;
App.js
import './App.css';
import CustomButton from './CustomButton';
function App() {
return (
<div className="App">
<CustomButton onClick={()=>alert("Clicked")}/>
</div>
);
}
export default App;
In the above case, nothing happens when button is clicked, because there is no onClick in CustomButton.js
However, if this is done:
CustomButton.js
import React from 'react';
const CustomButton = props => {
return (
<div onClick={props.onClick}>
<button>Click me</button>
</div>
);
};
export default CustomButton;
Now, the alert will appear when the button is clicked(or rather, when the div is clicked).
The name of the prop passed to CustomButton needn't have been onClick either, as the word has no significance when used on a custom component.
App.js
import './App.css';
import CustomButton from './CustomButton';
function App() {
return (
<div className="App">
<CustomButton anyprop={()=>alert("Clicked")}/>
</div>
);
}
export default App;
CustomButton.js
import React from 'react';
const CustomButton = props => {
return (
<div>
<button onClick={props.anyprop}>Click me</button>
</div>
);
};
export default CustomButton;
This works just fine as well, so long as the names of the prop being passed in CustomButton and App match.

My components are not being rendered when I click a link that should load them

I'm confused as to why nothing happens when I'm clicking links in my app.
In my index.js file, I am loading my main screen called 'Game'. Inside 'Game', I have two links, that when clicked, should render another screen.
In my index.js:
import React from "react";
import ReactDOM from "react-dom";
import Game from "./Game/Game";
ReactDOM.render(
<React.Fragment>
<Game/>
</React.Fragment>,
document.getElementById('gameContainer')
)
In my index.html:
<div>
<div id="gameContainer"></div>
</div>
<div id="root"></div>
My Game.js:
import React from "react";
import CharacterStats from "../CharacterStats";
import DungeonStats from "../DungeonStats";
const characterStatsComponent = () => {
return (
<CharacterStats />
);
}
const dungeonStatsComponent = () => {
return (
<DungeonStats />
);
}
const Game = () => (
<div>
<a id="showCharacter" href="#" onClick={characterStatsComponent}>Show your character</a>
</div>
<br />
<div>
<a id="showDungeon" href="#" onClick={dungeonStatsComponent}>Show current dungeon</a>
</div>
);
export default Game;
The two other components, CharacterStats and DungeonStats are just a few bits of html and reactjs to show some data.
Neither CharacterStats or DungeonStats are loading when I'm clicking the links.
I am also getting no errors in the console.
Nothing happens when the links are clicked.
I also put this inside each onClick event:
console.log('link was clicked');
And it does show the message in the console. So that shows that it knows the link is being clicked.
Is there anything that would prevent them from being loaded?
Thanks!
It wont work because you are returning jsx into the onClick function context, and not into the Game component's return value.
You could define a state using useState, something like showDungeon and showCharacter that defaults to false, change it to true onClick, and in the Game component's return value add:
{ showDungeon && <DungeonStats /> }
React uses something called Synthetic Events to achieve cross browser event handling. If I understood your question correctly than changing the onclick to onClick should do the job for you.

how can I dynamically attach sidebar components to multiple instances of sidebar?

I'm new to React and building out a design a ran into a problem.
I have a component called SideBar. I am using this component two times, one on each side of the page.
The problem is that I would like to add different components to each instance of the SideBar component. These would be lists of various items and etc. I assumed I could next component tags but the sidebar component doesn't output.
import React, { Component } from "react";
import SideBar from "./WorkspaceComponents/SideBar";
import ScrollerBox from "./WorkspaceComponents/SideBarComponents/ScrollerBox";
class Workspace extends Component {
render() {
return (
<main className="reely-workspace">
<SideBar position="SideBarLeft">
<ScrollerBox />
</SideBar>
<SideBar position="SideBarRight" />
</main>
);
}
}
export default Workspace;
Your sidebar component should receive a children prop and render it out.
Something like this:
class Sidebar extends Component {
render() {
const {children} = this.props;
return (
<div className="sidebar">
<h1>Sidebar</h1>
{children}
</div>
)
}
}
Check out this post on react docs to understand how to compose react components: https://reactjs.org/docs/composition-vs-inheritance.html
You can make your SideBar Component a wrapper component which wraps around the content given in it.
Making SideBar Component a Wrapper Component :
class Sidebar extends Component {
render() {
return (
<div className="sidebar">
// You can add any custom element here //
{this.props.children}
</div>
)
}
}
All your element passed inside the SideBar Component will now be rendered as a part of SideBar along with what it contains.
Way to consume the wrapper component:
<SideBar>
<Content1></Content1>
<Content2></Content2>
<Content3></Content3>
</SideBar>

Resources