I'm beginning to switch to functional/stateless components in React, like the one below.
I do however have a problem with react-chartjs-2 re-drawing my charts, even though the data for them didn't change. Before I switched to functional components, this was easily solved by using Reacts PureComponent.
Is there a way to make React use the PureComponent for a stateless function?
const ListGroup = props => {
const {title, width} = (props);
return (
<ul className={"grid"} style={{width}}>
<h1>{title}</h1>
{props.children}
</ul>
)
}
Since React v16.6.0 you can use React.memo():
import React from 'react';
const PureListGroup = React.memo(ListGroup);
With React versions before v16.6.0, You can use recompose (discontinued but still maintained) and wrap the component with the pure or onlyUpdateForKeys higher order components:
import pure from 'recompose/pure';
const PureListGroup = pure(ListGroup);
Related
ReactJS is a great library, However, it misses some features which I found in Vue and Angular. These features can be implemented of course in React, however, they require extra code to be written.
Every react component, or every JSX element I should say has the following properties shared, which are given by React to us to consume:
ref
key
I wanted to add extra props:
renderIf
fallback
These props help in a way I can't describe when it comes to conditional rendering and filtering the views based on the logged-in user permissions and roles (and other conditional rendering use cases, of course).
In react, if we wanted to apply these props to our components, we would use a HOC as follows:
// 🍎 Disclaimer: you don't have to understand any of the code written bellow, the general idea is that this is a HOC.
import React from 'react'
import getVal from './getVal'
export default function EnhancedComponent(OriginalComponent) {
return ({ renderIf: renderIf_ = true, override: override_, fallback: fallback_ = undefined, ...props }) => {
const renderIf = getVal(renderIf_)
const override = getVal(override_)
const fallback = getVal(fallback_)
const consumersComponent = <OriginalComponent {...props} />
let render = fallback
if (renderIf) render = consumersComponent
if (override_ !== undefined) render = override
return render
}
}
Where every time you want to apply these props to your components, you would have to wrap every new component you create with EnhancedComponent as follows:
export default EnhancedComponent(function Sidenav(){
return <div> side nav </div>
})
Now, you can use your Sidenav component within your App component as follows:
import Sidenav from './Sidenav'
export default function App(){
return (
<div>
<Sidenav renderIf={(5 + 5 === 10)}/>
<div>etc</div>
</div>
)
}
This API is great, but it has a drawback, which is, every time you want to apply these cool props (renderIf and fallback) you'll have to repeat these steps:
import Enhanced component to your file.
wrap your export with Enhanced component.
What I am looking for, is a method, or a way to inherit, or to add some props to the original react component class, somehow?
In react class components, I can imagine doing this on the React.Component class which we used to extend from in the past
class Car extends React.Component{
constructor(){}
render(){
return <div>I miss you 🌹</div>
}
}
But in react functional component, how can we do that?
I want to apply these props by default everytime I create a new component, without wrapping my components in a HOC everytime.
Does React have a way to do that? To change its defaults ?
in my company we are using ReactJS to develop our website. We also have legacy code in jQuery (I know, we are trying to change everything to React). My problem is that we have some global functions that we have to pass throughout all the component tree. For instance, we have a control function that we have to pass throughout 8 components, but only the last one actually calls it.
So, I wonder if there's a way to avoid this problem. Another problem is that we have several react trees on the page, because as I said, we have some legacy code in jQuery. Any ideas/suggestions?
(pls if this question does not belong in this forum let me know)
So you have to create yout context like this:
import React from "react";
const YourContext = React.createContext({ func: null });
export default YourContext ;
then in your parent component you can initialize it and make it available in child components:
import React from "react";
import YourContext from "./YourContext";
const YourParentComponent = () => (
<YourContext.Provider value={{ func: () => {} }}>
....
</YourContext.Provider>
);
and in your child components you can use it:
import React, { useContext } from "react";
import YourContext from "../YourContext";
const YourChildComponent = () => {
const { func } = useContext(YourContext);
Have a look at React Context, it will allow you to pass data through the components tree without passing down the props.
I've just updated a from a class based to a functional component.
When I look in React's DevTools, I'd usually see my component named Gallery with all the named state variables.
Now though, All I see is a component named _default with a bunch of non-descriptive State: definitions.
From other answers, I've read that React Dev Tools now supports hooks but I've not seen any examples of the component name being wrong.
Is this normal behaviour or is there something I'm doing wrong?
Versions
React 16.9.0
React Developer Tools Chrome extension: 4.1.1
Also getting the same issue in Firefox.
Component code
// The component
import React, { useState, useEffect } from 'react';
const Gallery = ({ images, layout }) => {
const [showLightbox, toggleLightbox] = useState(false);
const [activeImage, setActiveImage] = useState(false);
return (
// Some JSX here
)
};
Render code
// Rendering the component
import React from 'react';
import { render } from 'react-dom';
import Gallery from '../../global/scripts/components/Gallery';
render(
<Gallery images={images} />,
document.getElementById('image-gallery'),
);
Devtools screenshot
Try adding a displayName to your component before export. Check the following link for reference.
DisplayName
Use it like Gallery.displayName = 'Gallery'
What's the difference between import React from 'react' and import React { Fragment } from 'react' in context of <React.Fragment>, <Fragment> and <>?
I mean what happen when we import React and { Fragment } in the same line from a module?
Do we create instance of <Fragment> and this is just another few hundreds lines of code under the hood?
Or this is just normal and everybody can do that withouth performance downsides?
Official React blogpost mention that you can do this const Fragment = React.Fragment and they use in in their examples.
But why?
So assume you have an object.
let object = {
foo: '1',
bar: '2',
};
In order to use the value foo you can do the following
object.foo
let { foo } = object
These both are the same, the later mentioned way is called destructing which was introduced in javascript ES6 version.
Now coming to topic for
What's the difference between import React from 'react' and import React { Fragment } from 'react' in context of , and <>?
imagine React as object which has the following features e.g Fragment in this case. You can access it the following ways
1- First way
import React from 'react';
<React.Fragment></React.Fragment>
2-
import React, { Fragment } from 'react';
<Fragment></Fragment>
Now in the second way this is basically importing all React features and also destructing a feature from React which is Fragment. SO you don't have to write React.Fragment again and again.
3-
<></>
This is a babel feature, babel when compiling will convert <></> this into <React.Fragment></React.Fragment>
This is basically syntactic sugar:
import React, { Fragment } from 'react'
Will allow you to write the following:
class MyComponent extends React.Component {
render () {
return (
<Fragment>
<div className="fragment1">Fragment 1</div>
<div className="fragment2">Fragment 2</div>
<Fragment>
)
}
}
Instead of having to write explicitly React.Fragment. Note that you could also write the following if the only imports that you need are React.Component and React.Fragment:
import { Component, Fragment } from 'react'
class MyComponent extends Component {
render () {
return (
<Fragment>
<div className="fragment1">Fragment 1</div>
<div className="fragment2">Fragment 2</div>
<Fragment>
)
}
}
This may also become relevant when using module bundler such as Webpack, so your bundler will only import the required dependencies and it may result in a smaller bundle (AKA your app loads faster). Take a look at Tree Shaking for more details. This ultimately depends on how the imported package exports its modules, as mentioned in the reply above it may have no benefit for React - at the moment - but other libraries may leverage that mechanism. It is usually a good practice to try to keep your imports as strict minimum.
<></> syntax doesn’t support keys or attributes. When element is iterated it will throw the warning message 'Each child in a list should have a unique "key" prop'.
For Example :
{props.items.map(item => (
<>
<dt>{item.term}</dt>
<dd>{item.description}</dd>
</>
))}
See docs here https://reactjs.org/docs/fragments.html#keyed-fragments
Well there are no performance downsides, This is just have to do with extra markup. We do named export Fragment like Component that we usually do. As long as if you're concerned about performance, we're already importing from react which means complete react package Because there are not just Component, Fragment we need while exporting component in React Tree. There are under hood dependencies in react package we don't actually import but they are used in our component
How to signal to React that a functional component is "pure", as an equivalent of React.PureComponent for component classes?
function C(props) {
return <var>{props.n}</var>
}
without making it a class
class C extends React.PureComponent {
render() {
return <var>{this.props.n}</var>
}
}
As of React 16.6.0, memo has been added, so the answer is now:
const C = React.memo(props => {
return <var>{props.n}</var>
})
Based on the concept of purity in functional programming paradigms, a function is pure if:
Its return value is only determined by its input values
Its return value is always the same for the same input values
There seem two ways to do it for React functional components:
Using memo from react:
import React, { memo } from 'react';
const Component = (props) {
return (
// Component code
)
}
// Wrap component using "memo" HOC
export default memo(Component);
Using pure from recompose:
import React from 'react';
import { pure } from 'recompose';
const Component = (props) {
return (
// Component code
)
}
// Wrap component using "pure" HOC
export default pure(Component);
To #Shubham and #Andrew:
No, functional components are not PureComponents. Functional components will always get re-render if the parent component re-renders. A PureComponent contains a default shouldComponentUpdate() and I think that's what OP wants.
You can use pure provided by recompose to wrap and optimize your functional components:
import pure from 'recompose/pure'
const YourFunctionalComponent = (props) => {
...
}
export default pure(YourFunctionalComponent)
In addition to CodinCat answer.
The author of the library, recomponse, wrote a note on 25th Oct of 2018, where he stated, that what he tried to solve by the library was solved by the React Team through introducing hooks. Not only that, React team added optimization feature like React.memo(), which was named as React.pure() earlier. So, it's time to use React.memo(). Read Official Docs about it