In React, it is quite often used creating components without any state, just like function,
e.g.
const Count = () => {
return(
...some tags...
)
}
In this case, I see some cases that components with states are defined by extending components defined like above,
e.g.
class CounterContainer extends Count{
.... some codes
}
In my opinion, 'Count' component is not defined with typical class definition in javascript, but like a function.
But I can't tell it for sure... Is this only possible in React or generally ok in Javascript?
The reason why components are designed like that in React is because it makes components simpler when you don't need to handle state and so you don't need a lot of the boilerplate seen in traditional react classes with the constructor, render method, extends Component and so on. So you can have your simple, or as they're often referred to - dumb stateless components versus more complex stateful components.
Both are still valid Javascript. It's just a preference on how to write your code.
Related
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
Suppose I define a simple React functional component like this:
const Greeter1 = ({name}) => <h1>Hello {name}</h1>;
I can also define an equivalent plain-old JS function that returns a React element, like this:
const Greeter2 = name => <h1>Hello {name}</h1>;
The "React" version is of course also just a normal JS function, taking in a JS object instead of a string. We could use either of these functions within plain JS to get the greeter element for a given name, just with slightly different caller syntax:
const greeterElement1 = Greeter1({ name: "Bob" });
const greeterElement2 = Greeter2("Bob");
Within a React expression though, we can call these functions in a few different ways:
const someReact1 = <div>{ Greeter2("Bob") }</div>;
const someReact2 = <div>{ Greeter1({ name: "Bob" }) }</div>;
const someReact3 = <div><Greeter1 name="Bob" /></div>;
My question: Are there any effective differences between these calling styles other than syntax aesthetics? I assume someReact1 and someReact2 are virtually identical, but I'm not sure about someReact3. Does using the React component syntax change the way React treats things? Does it affect behavior or performance in any way? Or is it merely syntactic sugar?
When doing a diff on the virtual DOM tree, does React forgo comparing within a functional component if its attributes haven't changed between renderings? And if so, am I correct to assume that that optimization would be lost when calling functions directly as in someReact1?
I want to know b/c in some cases I actually prefer the style of someReact1 as it allows me to use functional programming techniques like currying more easily, plus sometimes it's nice to not have to specify parameter names when calling. But am I paying some kind of penalty by doing so? Am I better off sticking with the traditional syntax?
Component functions are (a bit?) faster than class components since React 16. Not sure if it's true for prior versions.
Calling component function as a function is much faster than calling it via JSX/React.createElement.
But, in most cases, this should not affect the way we write our code since JSX is pretty readable. To fill this gap we should use #babel/plugin-transform-react-inline-elements.
However, I understand your passion to call them as functions. For the sake of composition, I also find it quite useful. This is even more true for plain functions.
But, again, in the future, functional components are going to have a state. If it happens, we may regret our passion :)
Plain functions seem to be faster than component functions. However, I have not digged this topic yet. For example, I'm unsure if it works OK with react-hot-reload. Or, its pros/cons for performance and possible optimizations.
IMO, no matter the differences and in any case, optimizations are still on us - be it a shouldComponentUpdate, or memoization, or keys. Components which might not need any optimizations should be cheap to re-render, and vice versa (if it is a pure calculation, not DOM operation, obviously).
Feel free to comment or correct, I'll update my post.
I found an explanation, apparently someone asked a similar question in a Github issue on the official React repository. Here's a link to the issue https://github.com/facebook/react/issues/16796 and an excerpt from the thread, an answer provided by a contributor:
What I want to understand is this: Is it actually necessary to call
React.createElement again, since it is already in the return value of
the component? Is there any effective difference between that and
calling the function component directly, like this?
As #hamlim mentioned, the effective difference is that simply calling a component as a function wouldn't work if the component was more complex than a pure function that returned another React element. React needs the element returned from React.createElement to handle those features.
In the HelloMessage example you could technically just call it as a function, which would be equivalent to doing:
ReactDOM.render(
<div>Hello Taylor</div>,
document.getElementById("hello-example")
);
This just inlines the result of HelloMessage, which would render the same UI in the browser. Thats effectively what you're doing by calling HelloMessage as a function. Internally this would be different to React since there's no component mounted, but practically speaking the behavior is identical in this trivial example.
For the ParentComponent example, the same constraints apply. You could call the ChildComponent components as functions if they were just simple components without state or effects, and that would be the same result as just inlining their content into ParentComponent. In same cases this might be what you want, but typically not. If someone added state or effects to one of the ChildComponents, or wrapped it in React.memo or React.lazy, this would break. So use this pattern with caution.
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.
After struggling too much with Redux, flux and other pub/sub methods i ended up with the following technique. I do not know if that can cause some big damage or flaws so posting it here to get some light from the experienced programmers about its pros and cons.
var thisManager = function(){
var _Manager = [];
return{
getThis : function(key){
return _Manager[key];
},
setThis : function(obj){
_Manager[obj.key] = obj.value;
}
}
};
var _thisManager = new thisManager();
// React Component
class Header extends Component{
constructor(){
super();
_thisManager.setThis({ key: "Header", value:this}
}
someFunction(data){
// call this.setState here with new data.
}
render(){
return <div />
}
}
// Then from any other component living far somewhere you can pass the data to the render function and it works out of the box.
i.e.
class Footer extends Component{
_click(e){
let Header = _thisManager.getThis('Header');
Header.somefunction(" Wow some new data from footer event ");
}
render(){
return(
<div>
<button onClick={this._click.bind(this)}> send data to header and call its render </button>
</div>
);
}
}
I am sending json as a data in my application and it perfectly renders the desired components and i can invoke the render without any pub/sub or deep passing down the props to invoke a parent method with a changing this.setState to cause re-render.
So far the application works fine and i am also loving its simplicity too. Kindly throw light on this technique pros and cons
Regards
EDIT:
It is bad to call render so i changed it to another method to get more pros and cons of this setup.
Two main concerns with this setup:
1. You should never call react lifecycle methods directly
2. Backdoors into components are a bad idea, which destroy react's maintainability
Ad 1:
If you invoke render() (or any other react method) directly, react probably does not call componentDidMount(), componentDidUpdate()` and other lifecycle methods in the component tree.
Dangers are:
Many designs with react component rely heavily on the lifecycle methods being fired: getInitialState(), componentWillReceiveProps(), shouldComponentUpdate(), componentDidMount(), etc etc. If you call render() directly, many components will likely break or show strange behaviour.
You run the risk of breaking react's difference engine: through life-cycle management, react keeps a virtual copy of DOM in its (internal) memory. To work correctly, the integrity of this copy if vital to react's working.
Better would be (but still in violation of my second point):
Include a different method inside the component.
Which has a setState() if you want to re-render.
And call that method from the outside.
Ad 2.
A direct reference to a mounted component (as your thisManager does) has some additional risks. React's designs and limitations are there for a reason: to maintain unidirectional flow and component hierarchy with props and state, to make things easy to maintain.
If you break this pattern - by building a backdoor into a component, which allows manipulation of state - you break this design principle of react. It is a quick shortcut, but is sure to cause great pain and frustation when your app grows.
As far as I know, the only acceptable exceptions to this rule are:
Methods inside a component that respond to ajax call results, to update state (e.g. after fetching data from server)
Methods inside a component to handle triggers from its direct descendent children components (e.g. run validation on form after a child button has been clicked)
So if you want to use it for that purpose, then you should be fine.
Word of warning: the standard react approach guards random access to components, because the invoking component or method needs to have a reference to the component. In both examples such a reference is available.
In your setup, ANY outside piece of code could lookup the ref to the "header" in your table, and call the method which updates state.
With such indirect reference, and no way of telling which source actually called your component, your code is likely to become much harder to debug/ maintain.
Say I have a list of Posting components which can be of type say, Car, Truck or Boat.
The props to render each type of posting are the same, only the layout differs.
Should I create a separate component for each type? (CarPosting, TruckPosting), then render the correct one based on the type prop, or should I just have a partial render method for each type in the Posting component, which I then switch and call from the main render method?
You should have a separate component for each posting and then a wrapper component should decide which inner component to render.
The inner components
You should definitely have a separate component for each type, (CarPosting, TruckPosting...). These components should not have a type attribute, because when they are rendered, whoever is rendering should know whether they are a CarPosting, for instance.
As for whether you should use inheritance for these components or not, that depends on how much they share in terms of logic. If they only share some prop names, that alone does not justify using inheritance. In fact, most of the times there will be no need for inheritance in React components. There are some ways you can share behavior among your components without inheritance, like using Mixins or simply sharing some JS modules. That's actually up to you.
The wrapper component
Now, a wrapper component should determine which child components to render based on their type.
Yes, you can do switch and choose the component within that switch. If you have only 2 or 3 component type and you don't care too much about extensibility, that is acceptable.
However, a more sophisticated way of solving it would have a ComponentFactory in which you register a type and a component, like this:
// the first parameter is the type, the second is the Component
componentFactory.register("car", CarPosting);
componentFactory.register("boat", BoatPosting);
The componentFactory can have a buildComponent method accepting props, and repassing the props to a new instance of the component, according to what you have registered.
Example:
componentFactory.buildComponent("boat", someBoatProps)
Now, from your wrapper component, you can call the componentFactory for generating the components for you. Like this:
// this is inside the render method
<div>
{
postings.map(posting => componentFactory.buildComponent(posting.type, someOtherProps))
}
</div>