React.JS vs Vanilla JS, performance: (28x faster) - javascript

I'm starting to develop with React, I went through React Native first, so I'm a bit used to their ideas.
What's my problem with these structures:?
Performance, speed.
I wonder since then.
An example ? I realized when presented some mobile animations, they performed horrible when used in synchronous modes.
Maybe I didn't know the framework in an advanced way to understand it and extract its potential, but as you know, using it leaves you in the dark in some parts.
I'll leave here an example of how I reproduced this difference in speed between 'Vanilla JS' and React.JS.
React.JS
I'm just using an API to get all countries (250) and display them after the call.
This is the code: Main-> Container-> List-> Country,
I also used Styled Components, FontAwasome.
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import './api.js'
import styled from "styled-components";
import { FontAwesomeIcon } from "#fortawesome/react-fontawesome";
import { library } from "#fortawesome/fontawesome-svg-core";
import { faUser } from "#fortawesome/free-solid-svg-icons";
class Country extends React.Component {
clickChild = () => {
this.props.clicked(this.props.name)
}
render() {
return (
<Box onClick={this.clickChild} className="content">
<ImageBox flag={this.props.flag}>
<Icon num={this.props.num}><FontAwesomeIcon icon="user"/></Icon>
</ImageBox>
</Box>
);
}
}
class Lista extends React.Component {
constructor(props) {
super(props)
this.state = {lista:[]}
}
componentDidMount(){
let lista_temp = []
console.log("Iniciando requisição !")
fetch("https://restcountries.eu/rest/v2/all")
.then(resp => resp.json())
.then((json_data)=>{
for(var i=0;i<json_data.length;i++){
var population = (json_data[i].population).toLocaleString(undefined,{minimumFractionDigits: 0})
lista_temp.push({flag:json_data[i].flag,name:json_data[i].translations.br,num:population})
}
this.setState({lista:lista_temp})
console.log("Concluído !")
});
}
click(name){
window.open('https://pt.wikipedia.org/wiki/'+name,"_blank")
}
render() {
return (
<div className="lista">
{this.state.lista.map((tile,index) => (
<Country key={index} flag={tile.flag} name={tile.name} num={tile.num} clicked={this.click}/>
))}
</div>
);
}
}
class Container extends React.Component {
render() {
return (
<div className="container">
<div className="main_contant">
<Lista/>
</div>
</div>
);
}
}
class Main extends React.Component {
render() {
return (
<Container/>
);
}
}
// ========================================
ReactDOM.render(
<Main />,
document.getElementById('root')
);
When we look at the List component, do we have the use of Hooks? I can't say exactly what happens with this use, it seems to be the cause of the problems. Hooks are theoretically not supported in class components.
When we look at its usage, notice that I refresh the list after the entire API is complete, but I can make it much worse by calling setState on each loop item.
this.setState ({list: [... this.state.lista, {flag: json_data [i] .flag, name: json_data [i] .translations.br, num: population}]})
Here are the comparisons in terms of numbers.
A note: I won't put the Vanilla code (I'll leave a link if you like), but I'll show you its interface. It has a lot more interaction than React.
In React there is just one click of the event. In vanilla we have animations, autocomplete, consumption of another API and other events. And basically it's an '.append' html for each item consumed by the API.
I don't know why, but I changed the code to post here, and I realized there was an improvement, I don't understand, before it was between 6s - 9s, now it's 4s.
Vanilla
React and broken instruction;
What's wrong with my learning from this framework, any direction?
https://github.com/ricardosc12/stack_ask

Related

React StrictMode double initializasion - where to put logic that should be executed only once

I have a class inheriting React.Component as such :
import { Component } from "react"
import {Map} from "ol" // the goal is to render a map with openlayers
import './MapCanvas.css'
class MapCanvas extends Component {
constructor(props) {
super(props)
this.state = {}
}
componentDidMount() {
console.log('hello') // called twice
const canvas = new Map(/* map options, irrelevant here */)
this.setState({canvas})
}
componentWillUnMount () {
console.log('goodbye') // never called
if (this.state && this.state.canvas) {
this.state.canvas.setTarget(undefined) // should remove the map
}
}
render() {
return (
<div id="map" className="map"></div>
)
}
}
export default MapCanvas
My app looks like this
import MapCanvas from './components/MapCanvas'
import './App.css'
function App() {
return (
<MapCanvas/>
)
}
export default App
and index is
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import App from './views/App';
const root = createRoot(document.getElementById('app'))
root.render(
<StrictMode>
<App/>
</StrictMode>
)
If I remove StrictMode, Everything looks fine,
However if I leave it, the componentDidMount method of MapCanvas gets called twice, and I end up having 2 maps on the page. componentWillUnmount never gets called in the process.
I read here
and there
that React StrictMode calls some functions multiple times in Developpement mode.
As far as I understood, it is to help us code in a cleaner way, but I can't understand what I am supposed to do.
My question is, where am I supposed to setup the ol.Map so that it respects the best practices and gets called only once, OR gets properly "destroyed" on update ?
edit
just as posting the question I realized I had a typo on componentWillUnmount (M instead of m)
I Corrected it, now I see "goodbye" in the console, but I still have 2 maps.
If this question is more about openlayer thant about react, let it know in the comments and I'll update or delete it
edit #2
Using class attributes instead of React state to store the canvas gives the expected result.
Is this considered good practice or is there a better way ?
Here is a workaround that worked for me:
using a class attribute instead of the React State
import { Component, createRef } from "react"
import { Map } from "ol"
class MapCanvas extends Component {
constructor(props) {
super(props)
this.canvas = new Map(/* options */)
this.ref = createRef()
}
componentDidMount() {
this.canvas.setTarget(this.ref.current)
}
componentWillUnmount () {
this.canvas.setTarget(undefined)
}
render() {
return (
<div ref={this.ref} className="map"></div>
)
}
}
export default MapCanvas
It may not be good react practice, but it solves the prolem for now
If you have a better solution you can post an answer i'll consider accepting it instead

It is possible to import new property, functionality and html from other file to exists component?

I have the package with free and pro components.
I need to add new functionality (pro) for exists free component.
For example, I have a free component
import React from "react";
class Example extends React.Component {
constructor(props) {
super(props);
this.state = {
clickCounter: 0
}
}
addClick = () => {
this.setState({
clickCounter: this.state.clickCounter+1
})
}
render() {
return (
<button onClick={this.addClick}>Click {this.state.clickCounter}</button>
);
}
}
export default Example;
and in folder component/pro/ I want new functionality. (This folder is being deleted for the free package build)
And I would like the same component to have more possibilities under the same name for the pro version only.
For example, the limit of clicks.
What is the best way to do it?
Should I remove excess code from the component, or somehow can I load additional functions into an existing component.
If I understood the question correctly, you are distinguishing between a free and a Pro user, and based upon that you want to serve the respective features.
Your user details API should tell you about the user status, (Free or PRO). Based upon that response you can implement like below.
import FreeExample from './FreeExample';
import ProExample from './ProExample';
import AppLoader from './AppLoader';
class App extends React.Component {
isProUser = ({ userData }) => userData.status === 'PRO';
render() {
const { userData, isLoading } = this.props;
if(isLoading) return <AppLoader />
return (
{ isProUser({ userData }) ? <ProExample /> : <FreeExample />}
);
}
}

How can I prevent my functional component from re-rendering with React memo or React hooks?

When hiddenLogo changes value, the component is re-rendered. I want this component to never re-render, even if its props change. With a class component I could do this by implementing sCU like so:
shouldComponentUpdate() {
return false;
}
But is there a way to do with with React hooks/React memo?
Here's what my component looks like:
import React, { useEffect } from 'react';
import PropTypes from 'prop-types';
import ConnectedSpringLogo from '../../containers/ConnectedSpringLogo';
import { Wrapper, InnerWrapper } from './styles';
import TitleBar from '../../components/TitleBar';
const propTypes = {
showLogo: PropTypes.func.isRequired,
hideLogo: PropTypes.func.isRequired,
hiddenLogo: PropTypes.bool.isRequired
};
const Splash = ({ showLogo, hideLogo, hiddenLogo }) => {
useEffect(() => {
if (hiddenLogo) {
console.log('Logo has been hidden');
}
else {
showLogo();
setTimeout(() => {
hideLogo();
}, 5000);
}
}, [hiddenLogo]);
return (
<Wrapper>
<TitleBar />
<InnerWrapper>
<ConnectedSpringLogo size="100" />
</InnerWrapper>
</Wrapper>
);
};
Splash.propTypes = propTypes;
export default Splash;
As G.aziz said, React.memo functions similarly to pure component. However, you can also adjust its behavior by passing it a function which defines what counts as equal. Basically, this function is shouldComponentUpdate, except you return true if you want it to not render.
const areEqual = (prevProps, nextProps) => true;
const MyComponent = React.memo(props => {
return /*whatever jsx you like */
}, areEqual);
React.memo is same thing as React.PureComponent
You can use it when you don't want to update a component that you think is static so, Same thing as PureCompoment.
For class Components:
class MyComponents extends React.PureCompoment {}
For function Components:
const Mycomponents = React.memo(props => {
return <div> No updates on this component when rendering </div>;
});
So it's just creating a component with React.memo
To verify that your component doesn't render you can just
activate HightlightUpdates in react extension and check your components reaction on
rendering
We can use memo for prevent render in function components for optimization goal only. According React document:
This method only exists as a performance optimization. Do not rely on it to “prevent” a render, as this can lead to bugs.
According to react documentation:- [https://reactjs.org/docs/react-api.html][1]
React. memo is a higher order component. If your component renders the
same result given the same props, you can wrap it in a call to React.
memo for a performance boost in some cases by memoizing the result.
This means that React will skip rendering the component, and reuse the
last rendered result.
For practical understanding I came across these two videos they are very good if you wanna clear concepts also, better to watch so it'll save your time.
Disclaimer:- This is not my YouTube channel.
https://youtu.be/qySZIzZvZOY [ useMemo hook]
https://youtu.be/7TaBhrnPH78 [class based component]

Dynamically rendered Tag is always lowercase

I am trying to output some svgs and output them from a list, here is my render method:
render() {
const renderTag = () => {
const Tag = this.props.id
return(<Tag />)
}
return (
<div key={this.props.name} className="social-box">
<a className={this.props.id + "-link"}>
{renderTag()}
</a>
</div>
)
}
However, the DOM node is always lowercase i.e. <facebook> rather than <Facebook> this.props.id is correctly rendered to the console as Facebook. Can anyone tell me why react or the browser incorrectly renders as lowercase, and therefore not the component, and how to fix?
It's a technical implementation of React, all tags get lowercased on this line here, AFAIK it's not possible to render non-lowercased tags and that is by design.
Read more here.
i suggest that you would take a look at this article about dynamic components.
The most relevant example from the article:
import React, { Component } from 'react';
import FooComponent from './foo-component';
import BarComponent from './bar-component';
class MyComponent extends Component {
components = {
foo: FooComponent,
bar: BarComponent
};
render() {
const TagName = this.components[this.props.tag || 'foo'];
return <TagName />
}
}
export default MyComponent;
you most likely have a limited amount of components that could be rendered, so you might create a dictionary that contain a key (name of the component) to the component itself (as shown in the example) and just use it that way:
import Facebook from './FaceBook';
import Twitter from './Twitter';
const components = {
facebook: Facebook,
twitter: Twitter
};
render() {
return <div key={this.props.name} className="social-box">
<a className={this.props.id + "-link"}>
<components[this.props.id] />
</a>
</div>;
}
I find the answer eventually. #TomMendelson almost had the answer, but it needed fleshing out a bit more.
A function to create the component outside of the render method, suggested by #ShubhamKhatri actually did the job. Here's the final code:
import React from 'react';
import Facebook from './svg/Facebook';
import LinkedIn from './svg/LinkedIn';
import Twitter from './svg/Twitter';
import Pinterest from './svg/Pinterest';
class SocialMediaBox extends React.Component {
renderElement(item) {
const Components = {
'Facebook': Facebook,
'Twitter': Twitter,
'Pinterest': Pinterest,
'LinkedIn': LinkedIn
}
return React.createElement(Components[item], item);
}
render() {
const Element = this.renderElement(this.props.id)
return
(
<div>
{Element}
</div>
)
}
}
export default SocialMediaBox;
Thanks for the question and answers; alongside the answers given in Dynamic tag name in jsx and React they helped me to find a solution in my context (making a functional component in Gatsby with gatsby-plugin-react-svg installed):
import React from "react"
import FirstIcon from "../svgs/first-icon.inline.svg"
import SecondIcon from "../svgs/second-icon.inline.svg"
import ThirdIcon from "../svgs/third-icon.inline.svg"
const MyComponent = () => {
const sections = [
{ heading: "First Section", icon: () => <FirstIcon /> },
{ heading: "Second Section", icon: () => <SecondIcon /> },
{ heading: "Third Section", icon: () => <ThirdIcon /> },
]
return (
<>
{sections.map((item, index) => {
const Icon = item.icon
return (
<section key={index}>
<Icon />
<h2>{item.heading}</h2>
</section>
)
})}
</>
)
}
export default MyComponent
As mine is a Gatsby project I used the above mentioned plugin, but it itself process svgs with svg-react-loader so the basic principle should work in any React project using this package.

render array of object into a <li> in react.js

I read an article and the author critic below code, I wonder what's wrong with it. I was starting to learn React, too bad the author did not point out what's his problem with the code below. I tested the code below, it's running fine.
import React from 'react';
import './App.css';
const TodoItems = React.createClass({
getInitialState() {
return {
items : [
{id:1,name:"Gym"},
{id:2,name:"Jump"},
{id:3,name:"Racing"}
]
}
},
renderItem(){
return(
<ul>
{this.state.items.map((item,i) =>
<li key={i}>item.name</li>
)}
</ul>
)
},
render(){
return (
<renderItem />
)
}
})
ReactDOM.render(<TodoItems />,document.getElementById('app'));
The method renderItem should be outside as a functional or stateless component:
const RenderItem = (props) => {
return(
<ul>
{props.items.map((item,i) =>
<li key={i}>item.name</li>
)}
</ul>
)
};
The render method of the parent component should be:
render(){
return (
<RenderItem items={this.state.items} />
)
}
This is the standard way that we write React components. It causes maintainability issues when you write it that way.
In short, you code will not ensure component re-usability.
With React, you'll get the most of re-usability. In the above code, I can see that you are trying to render the items in the state in the function renderItem(). The need of using functions in any language is also to ensure re-usability. So, in React when you when you want to re-use a part which will return a HTML elements, make it as a separate component.
See the following fiddle
https://jsfiddle.net/Pranesh456/b6v6fxrj/1/
Here, I made the renderItem() as a separate component <RenderItem> which can be reused in n number of other components..

Categories

Resources