Why we cannot use hooks inside react class component ?. React Official documentation only say that hooks don't work inside class, But doesn't show why it won't work.
Class based components are components that extend the React.Component class.
Because of this, they have access to predetermined methods and have a specific lifecycle. For example, the render() method must be defined for class based components. More about the features of the component can be found here.
Historically, we couldn't use lifecycle methods in functional components or access state.
However, hooks were specifically introduced in React to provide this functionality to functional components. Meaning, hooks were only written for functional components when they were added.
Given the fundamental differences in the way React deals with functional components vs class based components and their different lifecycles- I suspect it wasn't feasible to try make hooks components compatible with class based components - especially as they already have access to state and their own lifecycle methods.
Moreover, given that a class component has specific methods, allowing both their existing methods and hooks would naturally lead to rendering chaos.
More can be found here on functional component lifecycle equivalents for class components.
This answer has more information on the fundamental differences and limitations of functional components vs class components - which will help elucidate why it's simple not possible to use their respective functionality in one another
Related
When I was learning react my instructor always remind me that I should use functional component as many as possible, try to avoid using class component, use class component sparingly. Yeah it was easy back then.
Now I am using Redux and I can barely using functional component because connect() imported from react-redux will only work with class component, as a result every component of my app are all class component. Is this normal? Since nowadays hooks API (which is using functional component) increasing in popularity.
Well, 2 things:
Firstly, it is possible to connect a functional component.
Secondly, you shouldn't be connecting every component to Redux. In reality the less components connected to Redux the better. Ideally, for a set of components, you have a 'container' component which is connected to the store (and which contains all the other relevant state and logic within it), then it passes that stuff down to the functional/class component children (which are more focused on presentation). Then you can have a few of these containers throughout the app, and the rest of the components are just traditional React ones.
If you connect everything directly to the store it can lead to problems like decreased reusability of components, poor performance or encouragement of bad component layout/hierarchy.
I find a bit of a discrepancy in React docs. In the section on Components and Props, they explain, through the example of a functional Welcome component, that
React calls the Welcome component with {name: 'Sara'} as the props.
Fair enough, given that the component is a pure function. Then in State and Lifecycle, they mention, through the example of a class Clock component, that
React calls the constructor of the Clock component. [...] React then calls the Clock component’s render() method.
From reading the docs, as well as this Medium post, with functional components,
the component is invoked directly as a function with props object
it returns a React element, i.e. an object that models the DOM element(s) to be rendered
React DOM then creates and inserts a DOM node to the "real" DOM
The flow is different with class-based components:
the component class is instantiated and the object instance is stored in memory
the render method is invoked and the React element (object) is returned
the React element, backed by its class instance, is used by React DOM to generate and mount an actual DOM node
The big difference, according to the article, is that "function components don’t have instances", meaning that they are invoked directly. React DOM "just uses the invocation of the function to determine what DOM element to render for the function".
However, this is incogruent with other sources. For instance, here and here Dan Abramov mentions that functional components are classes internally. In other words, React will just wrap a functional component into a class and instantiate it, as if it were a class component. Another article goes as far as saying that the former are even slower than the latter.
Question
Are functional components converted into class components by React?
Is there (yet) any performance benefits to using functional, rather
than class components? (e.g. here it says no benefits yet, I assume before React Fiber?)
Should I really sacrifice my workflow, if I
could have state across the app, where it would logically fit in, e.g. a form/controlled component somewhere deep down the tree?
Are functional components converted into class components by React?
There is no “optimized” support for them (functional component) yet because stateless component is wrapped in a class internally. It's same code path.
From a twitter thread by Dan Abramov.
Is there any performance benefits to using functional, rather than class components?
Apparently right now there is no performance benefits because React does a lot of things on Functional Components which decreases performance. Read this to gain more understanding.
Should I really sacrifice my workflow
I guess not
I cam across the definition of a component in the code base I'm working upon:
#PureRender
export default class UiWidget extends Component {
}
I tried googling to understand the significance of the attribute #PureRender which has been used to decorate the component but didn't get any relevant link. Can someone help me understand the impact of applying this attribute on a reactJs component?
There are three ways to define a react component:
Functional stateless component which doesn't extend any class
A component that extends PureComponent class
A normal component that extends Component class
For simple, presentation-only components that need to be easily reused, stateless functional components are preferred.
PureComponent overrides the shouldComponentUpdate for you and re-renders the component only if the props or state have actually changed. The important point here is it only does a shallow comparison of nextProps and nextState. You can read more here and here. #PureRender is simply the declarative way of saying that my reactJs component inherits from predefined PureComponent reactJs component.
Extending Component class helps to implement your own shouldComponentUpdate if you need some performance gains by performing you custom comparison logic between next/current props and state.
This is a javascript decorator, originally proposed in ES2016 (ES7). I believe they were removed from the proposal and postponed.
The purpose of the decorator is to add shouldComponentUpdate implementation with shallow property comparison.
Nowadays the same is done using extension from PureComponent:
export default class UiWidget extends React.PureComponent
I believe the decorator is not part of React, therefore it is probably implemented somewhere in your project, or in a dependency, similar to
pure-render-decorator.
Historically, React implemented that using pure-render-mixin, however mixins couldn't be used with ES6 classes (only with React.createClass) therefore alternative solutions were introduced. Decorators were one of them.
What is happening inside here from what I understand is that you're building out your own render method, which will render the html of the h1. This render method is called by React.DOM to figure out what to give to the virtual dom. The same goes for methods such as componentDidMount right? If you put in any of those lifecycle methods or render, React will call them accordingly to fit inside their code, but if create other functions, those will just be helper functions for you to render stuff with, right?
I guess I'm just trying to understand which part of the Component class is being used by React.DOM and which parts am I building. It seems weird that some methods are used to "configure" the component while others are used as helpers. What code inside the Component class is the React.DOM using? Is it like stuff to figure out the diffs on when to rerender stuff?
class Greeting extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
Here's something to consider: ages ago in times long past, React and React-DOM were one in the same. React was targeted solely to webapps. So we could use h1, div, span, img, all of that using React only.
Now let me ask you this question. Let's say they wanted to take React, and make it so it could not only render to the DOM of a webpage, but also render the different components of a native mobile application? What would you do in that situation?
Obviously, all of those aforementioned HTML DOM elements, h1s etc etc, would be utterly useless! Android and iOS interiors do not know what any of those are whatsoever.
So the logical solution is to abstract that away. Instead of having those DOM nodes be an inherent part of React, instead make it so that React can render wherever and whatever!
You see, the React engine works pretty much the same in both React Native (mobile development), and standard web-based React with React-DOM. The lifecycle methods, the principles of design, the reconciliation, the entire engine is the same. Because React isn't about HTML or native applications, it's about a paradigm of data flow from application state into UI state.
So then, what is React-DOM doing with your component? Not a whole lot of anything, really. All of the diffing, data flow, etc etc are all handled by React.
What React-DOM does is it knows how to render the data provided by a React element as a DOM node. It knows how to update them, how to delete, them, all of that. You see, having all those abilities as part of the React core would not be ideal now, because React targets other platforms where those abilities are useless. And they would only bloat the package.
The only method inside the class you 'have' to provide is the render. The other component lifecycle methods, as you mentioned, are called if provided when those lifecycle methods come into play. If you have no need to tap into those other lifecycle methods (component just returns some markup based on props provided to it) and your component doesn't need its own state then I would highly recommend just using stateless functional components. The docs provided by React team are good for explaining this -
https://facebook.github.io/react/docs/components-and-props.html
As far as the 'helper methods' you mentioned, yes you can define as many methods as you need in your class. It is very common to split up some of the more complex rendering logic into smaller easier to read functions for code readability.
After spending some time learning React I understand the difference between the two main paradigms of creating components.
My question is when should I use which one and why? What are the benefits/tradeoffs of one over the other?
ES6 classes:
import React, { Component } from 'react';
export class MyComponent extends Component {
render() {
return (
<div></div>
);
}
}
Functional:
const MyComponent = (props) => {
return (
<div></div>
);
}
I’m thinking functional whenever there is no state to be manipulated by that component, but is that it?
I’m guessing if I use any life cycle methods, it might be best to go with a class based component.
New Answer: Much of the below was true, until the introduction of React Hooks.
componentDidUpdate can be replicated with useEffect(fn), where fn is the function to run upon rerendering.
componentDidMount methods can be replicated with useEffect(fn, []), where fn is the function to run upon rerendering, and [] is an array of objects for which the component will rerender, if and only if at least one has changed value since the previous render. As there are none, useEffect() runs once, on first mount.
state can be replicated with useState(), whose return value can be destructured to a reference of the state and a function that can set the state (i.e., const [state, setState] = useState(initState)). An example might explain this more clearly:
const Counter = () => {
const [count, setCount] = useState(0)
const increment = () => {
setCount(count + 1);
}
return (
<div>
<p>Count: {count}</p>
<button onClick={increment}>+</button>
</div>
)
}
default export Counter
As a small aside, I have heard a number of people discussing not using functional components for the performance reasons, specifically that
"Event handling functions are redefined per render in functional components"
Whilst true, please consider if your components are really rendering at such a speed or volume that this would be worth concern.
If they are, you can prevent redefining functions using useCallback and useMemo hooks. However, bear in mind that this may make your code (microscopically) worse in performance.
But honestly, I have never heard of redefining functions being a bottleneck in React apps. Premature optimisations are the root of all evil - worry about this when it's a problem.
Old Answer: You have the right idea. Go with functional if your component doesn't do much more than take in some props and render. You can think of these as pure functions because they will always render and behave the same, given the same props. Also, they don't care about lifecycle methods or have their own internal state.
Because they're lightweight, writing these simple components as functional components is pretty standard.
If your components need more functionality, like keeping state, use classes instead.
More info: https://facebook.github.io/react/docs/reusable-components.html#es6-classes
UPDATE Jan 2023
TLDR; Functions are the best way to create components. React.Component is a legacy API.
"We recommend to define components as functions instead of classes."
"Class components are still supported by React, but we don’t recommend using them in new code."
https://beta.reactjs.org/reference/react/Component
UPDATE March 2019
Building on what was stated in my original answer:
Are there any fundamental differences between React functions and
classes at all? Of course, there are — in the mental model.
https://overreacted.io/how-are-function-components-different-from-classes/
UPDATE Feb 2019:
With the introduction of React hooks, it seems as though the React teams wants us to use functional components whenever possible (which better follows JavaScript's functional nature).
Their motivation:
It’s hard to reuse stateful logic between components.
Complex components become hard to understand.
Classes confuse both people and machines.
A functional component with hooks can do almost everything a class component can do, without any of the draw backs mentions above.
I recommend using them as soon as you are able.
Original Answer
Functional components aren't any more lightweight than class based components, "they perform exactly as classes." - https://github.com/facebook/react/issues/5677#issuecomment-241190513
The above link is a little dated, but React 16.7.0's documentation says
that functional and class components:
are equivalent from React’s point of view
https://reactjs.org/docs/components-and-props.html#stateless-functions
There is essentially no difference between a functional component and a class component that just implements the render method, other than the syntax.
In the future (quoting the above link):
we [React] might add such optimizations
If you're trying to boost performance by eliminating unnecessary renders, both approaches provide support. memo for functional components and PureComponent for classes.
https://reactjs.org/docs/react-api.html#reactmemo
https://reactjs.org/docs/react-api.html#reactpurecomponent
It's really up to you. If you want less boilerplate, go functional. If you love functional programming and don't like classes, go functional. If you want consistency between all components in your codebase, go with classes. If you're tired of refactoring from functional to class based components when you need something like state, go with classes.
Always try to use stateless functions (functional components) whenever possible. There are scenarios where you'll need to use a regular React class:
The component needs to maintain state
The component is re-rendering too much and you need to control that via shouldComponentUpdate
You need a container component
UPDATE
There's now a React class called PureComponent that you can extend (instead of Component) which implements its own shouldComponentUpdate that takes care of shallow props comparison for you. Read more
As of React 17 the term Stateless Functional components is misleading and should be avoided (React.SFC deprecated, Dan Abramov on React.SFC), they can have a state, they can have hooks (that act as the lifecycle methods) as well, they more or less overlap with class components
Class based components
state
lifecycle methods
memoization with React.PureComponent
Functional components:
state (useState, useReducer hooks)
lifecycle methods (via the useEffect, useLayoutEffect hooks)
memoization via the memo HOC
Why i prefer Funtional components
React provide the useEffect hook which is a very clear and concise way to combine the componentDidMount, componentDidUpdate and componentWillUnmount lifecycle methods
With hooks you can extract logic that can be easily shared across components and testable
less confusion about the scoping
React motivation on why using hooks (i.e. functional components).
I have used functional components for heavily used application which is in production. There is only one time I used class components for "Error Boundaries" because there is no alternative "Error Boundaries" in functional components.
I used "class component" literally only one time.
Forms are easier with functional, because you can reuse form input fields and you can break them apart with React display conditionals.
Classes are one big component that can't be broken down or reused. They are better for function-heavy components, like a component that performs an algorithm in a pop-up module or something.
Best practice is reusability with functional components and then use small functional components to assemble complete sections, ex.- form input fields imported into a file for a React form.
Another best practice is to not nest components in the process of doing this.
Class-based components offer a more structured and organized way to define and implement a component, and they provide additional features and capabilities, such as the ability to use local state and lifecycle methods. This can make them a good choice for creating complex components that require a lot of logic and functionality.
On the other hand, functional components are simpler and easier to work with, and they can be more performant because they are more lightweight. They are also easier to test and debug, because they are pure functions that don't have side effects. This makes them a good choice for creating simple components that don't require a lot of logic or state management.