Why use stateless functional Components instead of class-based Components? - javascript

I am learning ReactJS and I've learned that there are UI Components and Container Components. The Container Components are implemented using classes extending React.Component and contain state and good old render method, whereas the UI Components are created using functions and they are concerned with UI only as they only take the data from props.
Sample stateless functional components:
const Ninjas = (props) => {
const { ninjas } = props;
const ninjalist = ninjas.map((x) => {
var divStyle = {
color: getRandomColor(),
};
return (
<div className="ninja" key={x.key} style={divStyle}>
<p>Name: {x.name}</p>
<p>Age: {x.age}</p>
<p>Belt: {x.belt}</p>
</div>
);
});
return <div className="ninja-list">{ninjalist}</div>;
};
export default Ninjas;
The same sample as a Container Component
export default class Ninjas extends Component {
getRandomColor = () => {
....
return color;
};
render() {
const { ninjas } = this.props;
const ninjalist = ninjas.map((x) => {
var divStyle = {
color: this.getRandomColor(),
};
return (
<div className="ninja" key={x.key} style={divStyle}>
<p>Name: {x.name}</p>
<p>Age: {x.age}</p>
<p>Belt: {x.belt}</p>
</div>
);
});
return <div className="ninja-list">{ninjalist}</div>;
}
}
So my question is why do we even bother to make a UI component (not using the render method which is used in Container Component) when we could have easily done the same thing as a Container Component.

Functional state-less components (what wrongly you refer as UI Components, all components are UI components both statefull and stateless) are simply a short-hand method to create components that simply render something based on props passed and do not need to keep internal state.
Of course one can always use class-based components which extend React.Component. But why not have a short-hand to save time and space and simplify things if we can. There is nothing forcing you to create functional components, you can always use class-based components, only if you need to simplify and save time and space.
According to Functional vs Class-Components in React article:
So why should I use functional components at all?
You might ask yourself why you should use functional components at
all, if they remove so many nice features. But there are some benefits
you get by using functional components in React:
Functional component are much easier to read and test because they are plain JavaScript functions without state or lifecycle-hooks
You end up with less code
They help you to use best practices. It will get easier to separate container and presentational components because you need to think more
about your component’s state if you don’t have access to setState() in
your component
The React team mentioned that there may be a performance boost for functional component in future React versions
I would add a 5th point that React references (with React 16.3+) which provide functionality to access the DOM nodes directly cannot be used with Functional Components.
In React v.16.8+ useState hooks are introduced which enable functional components to be state-full while still being functional.
Furthermore with the introduction of React.memo higher-order component we can use memoization to avoid re-rendering of a functional component given that it renders same stuff for same props (shallow tested for difference)

Related

Should I wrap all my components with React.memo() if it is not expecting any props?

While it is obvious why React does not perform React.memo to all its functional component by default, and we should ourself wrap our functional components as and when needed.
In my case, I have a big react project with a structure like this:
const MyBigApp = () => {
const shouldShowX = useSelector(getShouldShowX);
const shouldShowY = useSelector(getShouldShowY);
// Many more selectors
return (
<>
{shouldShowX && <ComplexComponentX />}
{shouldShowY && <ComplexComponentY />}
{/* many more components based on different selectors like above */}
</>
);
};
All my business logic is inside redux and the components use useSelector internally to get data from the store.
Does it make sense to wrap all my child components with React.memo, as a change in any selector at root level causes my entire app to re-render?
Earlier with connect we were automatically getting a memoized component which was comparing custom props and store value passed as props to the component, so should we now manually always do React.memo while using useSelector in a component not receiving any props?
I would argue that you should consider using React.memo for those child components that don't accept any props. I highly recommend this article: https://dmitripavlutin.com/use-react-memo-wisely/
2.1 Component renders often with the same props
The best case of wrapping a component in React.memo() is when you expect the functional
component to render often and usually with the same props.
Since the components you're asking about don't accept any props, that means the props will never change. Therefore, it stands to reason that using React.memo could avoid render cycles. Note this important caveat from the same article:
5. React.memo() is a performance hint
Strictly, React uses memoization as a performance hint.
While in most situations React avoids rendering a memoized component,
you shouldn’t count on that to prevent rendering.

How can I correctly use the React context API in a class based component? [duplicate]

In this example, I have this react class:
class MyDiv extends React.component
constructor(){
this.state={sampleState:'hello world'}
}
render(){
return <div>{this.state.sampleState}
}
}
The question is if I can add React hooks to this. I understand that React-Hooks is alternative to React Class style. But if I wish to slowly migrate into React hooks, can I add useful hooks into Classes?
High order components are how we have been doing this type of thing until hooks came along. You can write a simple high order component wrapper for your hook.
function withMyHook(Component) {
return function WrappedComponent(props) {
const myHookValue = useMyHook();
return <Component {...props} myHookValue={myHookValue} />;
}
}
While this isn't truly using a hook directly from a class component, this will at least allow you to use the logic of your hook from a class component, without refactoring.
class MyComponent extends React.Component {
render(){
const myHookValue = this.props.myHookValue;
return <div>{myHookValue}</div>;
}
}
export default withMyHook(MyComponent);
Class components don't support hooks -
According to the Hooks-FAQ:
You can’t use Hooks inside of a class component, but you can definitely mix classes and function components with Hooks in a single tree. Whether a component is a class or a function that uses Hooks is an implementation detail of that component. In the longer term, we expect Hooks to be the primary way people write React components.
As other answers already explain, hooks API was designed to provide function components with functionality that currently is available only in class components. Hooks aren't supposed to used in class components.
Class components can be written to make easier a migration to function components.
With a single state:
class MyDiv extends Component {
state = {sampleState: 'hello world'};
render(){
const { state } = this;
const setState = state => this.setState(state);
return <div onClick={() => setState({sampleState: 1})}>{state.sampleState}</div>;
}
}
is converted to
const MyDiv = () => {
const [state, setState] = useState({sampleState: 'hello world'});
return <div onClick={() => setState({sampleState: 1})}>{state.sampleState}</div>;
}
Notice that useState state setter doesn't merge state properties automatically, this should be covered with setState(prevState => ({ ...prevState, foo: 1 }));
With multiple states:
class MyDiv extends Component {
state = {sampleState: 'hello world'};
render(){
const { sampleState } = this.state;
const setSampleState = sampleState => this.setState({ sampleState });
return <div onClick={() => setSampleState(1)}>{sampleState}</div>;
}
}
is converted to
const MyDiv = () => {
const [sampleState, setSampleState] = useState('hello world');
return <div onClick={() => setSampleState(1)}>{sampleState}</div>;
}
Complementing Joel Cox's good answer
Render Props also enable the usage of Hooks inside class components, if more flexibility is needed:
class MyDiv extends React.Component {
render() {
return (
<HookWrapper
// pass state/props from inside of MyDiv to Hook
someProp={42}
// process Hook return value
render={hookValue => <div>Hello World! {hookValue}</div>}
/>
);
}
}
function HookWrapper({ someProp, render }) {
const hookValue = useCustomHook(someProp);
return render(hookValue);
}
For side effect Hooks without return value:
function HookWrapper({ someProp }) {
useCustomHook(someProp);
return null;
}
// ... usage
<HookWrapper someProp={42} />
Source: React Training
you can achieve this by generic High order components
HOC
import React from 'react';
const withHook = (Component, useHook, hookName = 'hookvalue') => {
return function WrappedComponent(props) {
const hookValue = useHook();
return <Component {...props} {...{[hookName]: hookValue}} />;
};
};
export default withHook;
Usage
class MyComponent extends React.Component {
render(){
const myUseHookValue = this.props.myUseHookValue;
return <div>{myUseHookValue}</div>;
}
}
export default withHook(MyComponent, useHook, 'myUseHookValue');
Hooks are not meant to be used for classes but rather functions. If you wish to use hooks, you can start by writing new code as functional components with hooks
According to React FAQs
You can’t use Hooks inside of a class component, but you can
definitely mix classes and function components with Hooks in a single
tree. Whether a component is a class or a function that uses Hooks is
an implementation detail of that component. In the longer term, we
expect Hooks to be the primary way people write React components.
const MyDiv = () => {
const [sampleState, setState] = useState('hello world');
render(){
return <div>{sampleState}</div>
}
}
You can use the react-universal-hooks library. It lets you use the "useXXX" functions within the render function of class-components.
It's worked great for me so far. The only issue is that since it doesn't use the official hooks, the values don't show react-devtools.
To get around this, I created an equivalent by wrapping the hooks, and having them store their data (using object-mutation to prevent re-renders) on component.state.hookValues. (you can access the component by auto-wrapping the component render functions, to run set currentCompBeingRendered = this)
For more info on this issue (and details on the workaround), see here: https://github.com/salvoravida/react-universal-hooks/issues/7
Stateful components or containers or class-based components ever support the functions of React Hooks, so we don't need to React Hooks in Stateful components just in stateless components.
Some additional informations
What are React Hooks?
So what are hooks? Well hooks are a new way or offer us a new way of writing our components.
Thus far, of course we have functional and class-based components, right? Functional components receive props and you return some JSX code that should be rendered to the screen.
They are great for presentation, so for rendering the UI part, not so much about the business logic and they are typically focused on one or a few purposes per component.
Class-based components on the other hand also will receive props but they also have this internal state. Therefore class-based components are the components which actually hold the majority of our business logic, so with business logic, I mean things like we make an HTTP request and we need to handle the response and to change the internal state of the app or maybe even without HTTP. A user fills out the form and we want to show this somewhere on the screen, we need state for this, we need class-based components for this and therefore we also typically use class based components to orchestrate our other components and pass our state down as props to functional components for example.
Now one problem we have with this separation, with all the benefits it adds but one problem we have is that converting from one component form to the other is annoying. It's not really difficult but it is annoying.
If you ever found yourself in a situation where you needed to convert a functional component into a class-based one, it's a lot of typing and a lot of typing of always the same things, so it's annoying.
A bigger problem in quotation marks is that lifecycle hooks can be hard to use right.
Obviously, it's not hard to add componentDidMount and execute some code in there but knowing which lifecycle hook to use, when and how to use it correctly, that can be challenging especially in more complex applications and anyways, wouldn't it be nice if we had one way of creating components and that super component could then handle both state and side effects like HTTP requests and also render the user interface?
Well, this is exactly what hooks are all about. Hooks give us a new way of creating functional components and that is important.
React Hooks let you use react features and lifecycle without writing a class.
It's like the equivalent version of the class component with much smaller and readable form factor. You should migrate to React hooks because it's fun to write it.
But you can't write react hooks inside a class component, as it's introduced for functional component.
This can be easily converted to :
class MyDiv extends React.component
constructor(){
this.state={sampleState:'hello world'}
}
render(){
return <div>{this.state.sampleState}
}
}
const MyDiv = () => {
const [sampleState, setSampleState] = useState('hello world');
return <div>{sampleState}</div>
}
It won't be possible with your existing class components. You'll have to convert your class component into a functional component and then do something on the lines of -
function MyDiv() {
const [sampleState, setSampleState] = useState('hello world');
return (
<div>{sampleState}</div>
)
}
For me React.createRef() was helpful.
ex.:
constructor(props) {
super(props);
this.myRef = React.createRef();
}
...
<FunctionComponent ref={this.myRef} />
Origin post here.
I've made a library for this. React Hookable Component.
Usage is very simple. Replace extends Component or extends PureComponent with extends HookableComponent or extends HookablePureComponent. You can then use hooks in the render() method.
import { HookableComponent } from 'react-hookable-component';
// 👇👇👇👇👇👇👇👇
class ComponentThatUsesHook extends HookableComponent<Props, State> {
render() {
// 👇👇👇👇👇👇
const value = useSomeHook();
return <span>The value is {value}</span>;
}
}
if you didn't need to change your class component then create another functional component and do hook stuff and import it to class component
Doesn't work anymore in modern React Versions. Took me forever, but finally resulted going back to go ol' callbacks. Only thing that worked for me, all other's threw the know React Hook Call (outside functional component) error.
Non-React or React Context:
class WhateverClass {
private xyzHook: (XyzHookContextI) | undefined
public setHookAccessor (xyzHook: XyzHookContextI): void {
this.xyzHook = xyzHook
}
executeHook (): void {
const hookResult = this.xyzHook?.specificHookFunction()
...
}
}
export const Whatever = new WhateverClass() // singleton
Your hook (or your wrapper for an external Hook)
export interface XyzHookContextI {
specificHookFunction: () => Promise<string>
}
const XyzHookContext = createContext<XyzHookContextI>(undefined as any)
export function useXyzHook (): XyzHookContextI {
return useContext(XyzHookContextI)
}
export function XyzHook (props: PropsWithChildren<{}>): JSX.Element | null {
async function specificHookFunction (): Promise<void> {
...
}
const context: XyzHookContextI = {
specificHookFunction
}
// and here comes the magic in wiring that hook up with the non function component context via callback
Whatever.setHookAccessor(context)
return (
< XyzHookContext.Provider value={context}>
{props.children}
</XyzHookContext.Provider>
)
}
Voila, now you can use ANY react code (via hook) from any other context (class components, vanilla-js, …)!
(…hope I didn't make to many name change mistakes :P)
Yes, but not directly.
Try react-iifc, more details in its readme.
https://github.com/EnixCoda/react-iifc
Try with-component-hooks:
https://github.com/bplok20010/with-component-hooks
import withComponentHooks from 'with-component-hooks';
class MyComponent extends React.Component {
render(){
const props = this.props;
const [counter, set] = React.useState(0);
//TODO...
}
}
export default withComponentHooks(MyComponent)
2.Try react-iifc: https://github.com/EnixCoda/react-iifc

Are React functional components really more lightweight than class components?

I've read in a few places that functional components are more lightweight than class components, and from here it sounds like Facebook intends for functional + hooks to be the preferred paradigm for new components.
The problem I see is that with functional components things like class methods get redefined on every render, instead of just once. Is this not an issue, or do the other advantages of functional components simply outweigh this?
Example for clarity:
Class Component
class SignInForm extends React.Component {
...
// Only gets defined when the component is created with `React.createElement`
submit = () => {
// send POST request to get an auth token, etc.
}
render() {
<form>
...
<button onClick={this.submit}>Sign In</button>
</form>
}
}
Functional Component
function SignInForm (props) {
...
// Gets defined on every render, since this essentially *is* the `render` function
const submit = () => {
// send POST request to get an auth token, etc.
}
return (
<form>
...
<button onClick={submit}>Sign In</button>
</form>
);
}
Slowest part in web apps is the rendering. So creating a new function on every render is not a big deal. Also for web apps, build size matter and for functional components, minification works better than as it works for class-based components.
With the release of new features like memo, useMemo, useCallback etc. we can get the same performance as we get with class-based components.
React community is moving towards functional components and hooks which is an indication that functional components are not bad.

How to make props immutable to prevent rerender in React?

I have been creating a small app using react.js. I take 'performance' into account excessively.
So I have a simple child component named "Spinner". My goal is to make sure this component never re-renders.
Here is my component:
import React, {PureComponent} from 'react';
export default class Spinner extends PureComponent {
render() {
return (
<div className="spinner">
<div className="bounce1"></div>
<div className="bounce2"></div>
<div className="bounce3"></div>
</div>
)
}
}
In the time of the re-rendering with 'react-addons-perf', the component is always rendering, I am using PureComponent because I want that component to render only one time, I read that I can use immutable props but I don't know how to make this possible.
If I make some like to this:
componentDidMount() {
this.renderState = false;
}
shouldComponentUpdate(nextProps, nextState) {
return (this.renderState === undefined) ? true : this.renderState;
}
It is rendering only one time, but I believe that there is a better way.
How do I avoid the re-render? or maybe How I can make a immutable props?
You don't need an extra logic for componentShouldUpdate, since you don't want your component to rerender ever.
Adding only this should be enough to prevent component to rerender:
shouldComponentUpdate(nextProps, nextState) {
return false
}
For stateless components that don't need props, we can use a combination of a Functional (stateless) component, and babel's React constant elements transformer to optimize the component creation, and prevent rerenders entirely.
Add React constant elements transformer to your build system. According to the docs the transformer will:
Hoists element creation to the top level for subtrees that are fully
static, which reduces call to React.createElement and the resulting
allocations. More importantly, it tells React that the subtree hasn’t
changed so React can completely skip it when reconciling.
Change the spinner to a stateless component.
const Spinner = () => (
<div className="spinner">
<div className="bounce1"></div>
<div className="bounce2"></div>
<div className="bounce3"></div>
</div>
);
export default Spinner;
You can make your props immutable in React by using Immutable JS to transform your array props into Lists and object props int Maps. With this library you can use simple checks to check the equality of arrays/objects (instead of going through keys/values for equality):
shouldComponentUpdate(nextProps) => {
this.props.complexObjectAsMap === nextProps.complexObjectAsMap
}
But since your component doesn't have any props - this doesn't look the right question. In your case I'd go with Ori Drori answer.

What's the difference between using a stateless functional component versus calling a method?

I'm trying to understand stateless components and what the difference is between these examples:
class App {
render() {
return (
<div>
{this.renderAFunction('hello')}
</div>
);
}
renderAFunction(text) {
return (
<p>{text}</p>
);
}
}
and this:
class App {
render() {
return(
<div>
<RenderAFunction text='hello'/>
</div>
);
}
}
const RenderAFunction = ({text}) => (
<p>{text}</p>
);
Or if there is any difference at all?
Functionally, there is absolutely no difference. Both end up rendering a paragraph element, but there are other aspects to consider. There are three points to make (in my opinion) when examining both methods:
Reusability: You have to understand to separate components when you need to. If renderAFunction is just meant to generate some JSX based on, for example, an API request, then it's fine being in a method. But if you want to reuse it somewhere else, then separate it into it's own component. A huge part of React is component reusability and getting rid of code duplication. Separating the method into it's own component would be imperative to accomplish this.
Purpose: There are reason to use stateless function components and reasons not to. The whole point of stateless functional components is to not have state and be presentational. If you need to do something that involves the React lifecycle or internal state, keep it as a method, or new class depending on if you want it reusable.
Performance: Using a stateless functional component would be less efficient. This is because it's a component, not just some JSX returned from a method. As of right now, the React team plans on making some optimizations for stateless functional components because they do not contain state and are merely presentational, but this probably won't happen until after React Fiber is done and thus your stateless functional component has no optimizations versus a regular full-fledged class component. That makes it incredibly inefficient versus a method returning some JSX, especially if it's just used once in another component.
A good rule of thumb is to ask yourself, do I need it anywhere else? If not, then keep it in a method. If you don't need it anywhere else, separating the JSX into a separate component would have worse performance and wouldn't follow React's core principles.
If you are going to need it somewhere else, then separate the component so you follow React's concept of reusability.
Your App's render function will be translated into following JS code for your first example:
render() {
return React.createElement(
'div',
null,
this.renderAFunction('hello')
);
}
And the following one for the second one:
render() {
return React.createElement(
'div',
null,
React.createElement(RenderAFunction, { text: 'hello' })
);
}
While they both looks almost the same, there is one significant difference: laziness. React will execute RenderAFunction body only in case it gonna be mounted to the DOM hierarchy.
It is insignificant is your case, but imaging following example:
const LazyApp = () => {
const heavy = <div><HeavyStuff /></div>
// ...
return <div>done it</div>
}
const HardWorkingApp = () => {
const heavy = <div>{HeavyStuff()}</div>
// ...
return <div>done it</div>
}
const HeavyStuff = () => {
// ... do heavy rendering here
}
Lazy app will not perform any heavy stuff at all. Maybe it is not very clear from that synthetic example why one would do anything like that at all. But there are real-world examples out there, when something conceptually similar (creating Components without rendering them) is happening.
Basically, both will serve the same purpose. But the real advantage of creating a component is its reusability.
If you have to render that particular piece of jsx just for this component. Then, there is no need to create a separate component.

Categories