How to render new React Component into rendered DOM? - reactjs

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.

Related

React: Why sibling components are re-rendered when setValue of hooks is called and how can I stop this. Please the code below

//Example Component
import React, { useState } from 'react';
import IndependentComponent from './independent-component'
function Example() {
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
<IndependentComponent />
</div>
);
}
//Independent Component
import React from 'react'
const IndependentComponent = function () {
console.log('This component is rendered when setCount is called in Example component')
return (
<div>Independent Sibling Component </div>
)
}
export default IndependentComponent
When a parent component is re-rendered, so are all its children. Thus even though IndependentComponent does not change with changes in parent component, it will still forcibly go through the render cycle.
There are 2 ways to prevent this, depending on whether it is a class based component or functional component.
For class based components, you could either extend the PureComponent class to never go through re-render cycle, or you could use shouldComponentUpdate for more fine tuned control of when the component should re-render.
In the functional components case, which you are looking for, you can use React.memo HOC to make it behave like PureComponent, with the optional callback function to also have the fine-tuned control of shouldComponentUpdate.
So, in your use case of functional component, all you need to do is export your independent component like:
export default React.memo(IndependentComponent);

how are child class components in reactjs are called .Can any one tell me the flow of the following program

program:-
import React from 'react';
import ReactDOM from 'react-dom';
// Parent Component
class Parent extends React.Component{
render(){
return(
<div>
<h2>You are inside Parent Component</h2>
<Child name="User" userId = "5555"/>
</div>
);
}
}
// Child Component
class Child extends React.Component{
render(){
console.log(this.props);
return(
<div>
<h2>Hello, {this.props.name}</h2>
<h3>You are inside Child Component</h3>
<h3>Your user id is: {this.props.userId}</h3>
</div>
);
}
}
ReactDOM.render(
// passing props
<Parent />,
document.getElementById("root")
);
I can see that the parent class is been called using the render method dint have any idea how the class component child is called.
Here's an explanation from the React docs:
Components can refer to other components in their output. This lets us use the same component abstraction for any level of detail. A button, a form, a dialog, a screen: in React apps, all those are commonly expressed as components.
Your Parent component refers to the Child component; when Parent is rendered, Child is as well, with the props name and userId.
Composing Components

Sending a React.FunctionComponent<React.SVGProps<SVGSVGElement>> as a prop to another component

I'm attempting to import a React functionComponent from an SVG and then send that to another component as a prop to render that svg. With the setup below, this compiles fine, but eventually crashes when trying to render the svg in browser with:
Error: Objects are not valid as a React child (found: object with keys {$$typeof, render}). If you meant to render a collection of children, use an array instead.
Classes below are simplified. But the gist of what I'm trying to do is:
In overlay.tsx:
import { ReactComponent as icon } from "/icon.svg";
import CustomItem from "/customItem";
const Overlay: React.FC<OverlayProps> = () => {
return (
<div>
<CustomItem icon={icon}/>
</div>
);
export default Overlay;
}
and in customItem.tsx:
import React from "react";
export interface CustomItemProps {
icon: React.FunctionComponent<React.SVGProps<SVGSVGElement>>;
}
const CustomItem: React.FC<CustomItemProps> = ({icon}) => {
return (
<div>
{icon}
</div>
);
};
export default ApplicationsDropdownItem;
I assume my problem is somewhere around the syntax of {icon}, but I can not for the life of me find out what I'm suppose to use instead.
Answer
The icon you are importing is a component, therefore it must be called to render the JSX.
<Icon {...props}/> (correct) or {Icon(props)} (not recomended)
Since it is a component, you should also name it Icon and not icon.
Take a look at this blog post that explains SVGR.
TL;DR - Best approach for rendering components
A. Call the component in your render method with component syntax <MyComponent/> not MyComponent().
B. Instantiate your component as a variable, and pass that to your render method's JSX block.
More info
#DustInCompetent brought to light the issue of calling a component as a function inside a JSX block.
As explained here and here, that will lead to react not registering a components hooks and lead to state and other problems.
If you are implementing a High Level Component (HOC), then you should not call a component within the render method (return statement in functional components), as this leads to problems for similar registration issues of the component.
import React from "react";
import { ReactComponent as SampleIcon } from "/sample_icon.svg";
export interface CustomItemProps {
Icon: React.FunctionComponent<React.SVGProps<SVGSVGElement>>;
}
const CustomItem: React.FC<CustomItemProps> = (props) => {
const Temp = props.Icon as React.FunctionComponent<React.SVGProps<SVGSVGElement>>;
return (
<div>
<Temp/>
</div>
);
};
<CustomItem Icon={SampleIcon}/>
I think you should use <Icon /> instead of {icon} because it's a component.

React Transition Group

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>
)
}

React rerenders whole component when its properties change

Let's consider the following sample:
import React, {Component} from 'react';
class B extends Component {
render() {
console.log(`Render runs with ${this.props.paramA}`);
return (<div>{this.props.paramA}</div> );
}
}
class App extends Component {
constructor() {
super();
this.state = {paramA: 'asd'};
}
handleChange(event) {
this.setState({paramA: event.target.value});
}
render() {
return (<div>
<input value={this.state.paramA} onChange={e => this.handleChange(e)}/>
<label>
<B paramA={this.state.paramA}></B>
</label>
</div>);
}
}
Here's the gif of how it works.
If you noted, in order to update the changes from properties, react needs to evaluate "render" method. That causes the whole component to update instead of its small part that really changed (check the gif, the div element blinks in chrome developer tools):
TL;DR According to react philosophy,apps should be written in a way to have as many dummy components as possible. That means we have to pass properties a few level down sometimes (other time we can use e.g. redux), which leads to a lot of render methods that evaluate every time the property of top level component changes. With all that being said I often see in the real life react application that a whole root div blinks when e.g. users types something into input. Well even if it's a browser "lag" I don't really like the idea that react reevaluates all components (meaning running their render method) when a component needs to update only its small part.
The question:
Am I doing something wrong? Is there a way to implement react component so they update only things that changed?
It sounds like you're looking for the shouldComponentUpdate lifecycle hook.
Pretty self explanatory; if the component should only re-render under specific prop/state changes, you can specify those in this hook, and return false otherwise.
In this case, React is not rerendering the entire component but the first parent of the dynamic part of them. In this case, the <div> is the parent (and the entire component so you're right), but in this fiddle wrapping {this.props.paramA} inside a paragraph tag, the <div> is not the direct parent, so just rerenders <p> tag and <div> does not need to update.
class B extends React.Component {
render() {
console.log(`Render runs with ${this.props.paramA}`);
return (<div><p>{this.props.paramA}</p></div> );
}
}
class App extends React.Component {
constructor() {
super();
this.state = {paramA: 'asd'};
}
handleChange(event) {
this.setState({paramA: event.target.value});
}
render() {
return (<div>
<input value={this.state.paramA} onChange={e => this.handleChange.bind(this)(e)}/>
<label>
<B paramA={this.state.paramA} />
</label>
</div>);
}
};
ReactDOM.render(
<App />,
document.getElementById('container')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="container"></div>

Resources