I have been reading about React Transition Group. 95% of the material talks about CSSTransitionGroup. My understanding is that CSSTransitionGroup just builds off of TransitionGroup which simply provides callback methods that correspond to various animation events.
So I've wrapped my component up in a TransitionGroup element and given it an animation event but it is never fired.
import React, { Component } from "react";
import { TransitionGroup, Transition } from "react-transition-group";
class Test extends Component {
componentWillAppear(cb) {
console.log('componentWillAppear')
cb()
}
render() {
return <div> test </div>
}
}
class App extends Component {
render() {
return (
<TransitionGroup>
<Test />
</TransitionGroup>
)
}
}
export default App;
You can use Transition or CSSTransition without TransitionGroup, but you can't use TransitionGroup without one of the others.
From the react-transition-group docs:
The <TransitionGroup> component manages a set of <Transition> components in a list. Like with the <Transition> component, <TransitionGroup>, is a state machine for managing the mounting and unmounting of components over time.
...As items are removed or added to the TodoList the in prop is toggled automatically by the <TransitionGroup>.
Try changing your Test component's render to something like this:
render() {
return (
<Transition timeout={150}>
{(status) => (
<div className={`fade fade-${status}`}>
test
<div>
)}
</Transition>
)
}
Related
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
I'm using Material UI's switch to change themes on a multi-page app. The only bug that happens is the switch does not move from left to right (ui functionality does not occur), but the onChange functionality is working fine. I played around with it, turns out that when I remove forceUpdate(), the material ui switch will work, but the component will not be rerendered. What in forceUpdate is preventing the switch functionality from working?
App.tsx :
import React from "react"
import {Switch, Route, BrowserRouter, Redirect} from "react-router-dom"
import Main from "./Main"
import {createMuiTheme, ThemeProvider} from "#material-ui/core";
class App extends React.Component<any, any>{
darkmode=true
theme=createMuiTheme({
palette:{
type:this.darkmode?"dark" : "light"
},
})
changeTheme=()=>{
this.darkmode=!this.darkmode;
this.theme = createMuiTheme({
palette:{
type:this.darkmode?"dark" : "light"
}
})
this.theme.spacing(10)
this.forceUpdate()
}
render(){
return(
<div>
<BrowserRouter>
<Switch>
<Route path="/" component={()=>
<Main theme={this.theme} changeTheme={this.changeTheme} />
}
</Switch>
</BrowserRouter>
</div>
)
}
}
Main.tsx:
class Main extends React.Component<any,any>{
render(){
return(
<div>
<Switch onChange={()=>this.props.changeTheme()}></Switch>
<Switch></Switch>
</div>
)
}
}
you didn't use states the UI will not rerender if you don't pass a new state
constructor(props) {
super(props);
this.state = {darkmode: true};
}
this.setState({
darkmode: !darkmode
});
the two piece of code here will help you the first one in the initialize of the state
and the second is the update
By default, when your component’s state or props change, your component will re-render. If your render() method depends on some other data, you can tell React that the component needs re-rendering by calling forceUpdate().
take from react doc that explain
what it's do basically it's rernder by force the component you should avoid to all use and make the read from the props and state
I would like to know, is it possible to run script only for 1 component?
In my code I have imported 5 components
import React from 'react';
import Intro from './includes/Intro';
import Counter from './includes/Counter';
import Feedback from './includes/Feedback';
import FeedbackAll from './includes/FeedbackAll';
import Faq from './includes/Faq';
class Home extends React.Component {
render() {
return(
<main>
<Intro />
<Counter />
<Feedback />
<FeedbackAll />
<Faq />
</main>
)
}
}
export default Home
So I have some script which I want to run only for the component <Counter />
When I write that script inside of that component, it runs in every single component of my project.
This is the file Counter.js
import React from 'react';
const Counter = () => {
return (
<section id="benefits">
</section>
);
};
window.addEventListener('scroll', function() {
let hT = document.querySelector("#benefits").offsetTop;
alert (hT)
});
export default Counter
When I navigate another page, on scroll the script still works and looking for the element #benefits, and shows error.
So I need to run that script only inside of the component Counter.js
Please help me to do that!
You should refactor counter.js as class component. Trick is to move event listeners inside class definition and remove event listeners when un-mounting the class.
Now only in the pages you user <Counter />, scroll listeners are attached and it gets removed when <Counter /> component is un-mounted.
Solution here 👇
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>
I have three component parent and 2 childs:
import React from 'react';
import FirstChild from './FirstChild';
import SecondChild from './SecondChild';
export default class ComponentName extends React.Component {
render() {
return (
<div>
<h1>ComponentName</h1>
<div id="renderChildHere">
<FirstChild />
</div>
<button onClick={this.clickHandler}>Replace FirstChild with SecondChild</button>
</div>
);
}
clickHandler() {
???
}
}
The FirstChild is initially rendered. How do I unmount it and mount the SecondComponent in the #renderChildHere Dom element?
I use React 0.13.3 and Flux without third-party addons.
You should have a state on ComponentName that tells which child component to render. For simplicity, I'm gonna call it childComponentName and it can hold either firstComponent and secondComponent as strings. On your this.clickHandler, you should do something like this:
this.setState({childComponentName: 'secondComponent'});
Now React is going to render ComponentName again. Within the render method, you can choose whether to render <FirstComponent/> or <SecondComponent/> based on the value of the childComponentName state.
Of course this is just for simplicity, so you can understand the concept.
You'll only manually mount and unmount components in very specific scenarios. For all the others, this is the way to go.