The question is aligned more towards the performance or best practices of implementation.
As per React Docs, refs, which are part of React16 can only be used in class-based(stateful) components. As stateless components do not have an instance or state we cannot have refs in the stateless component.
What is the tradeoff of changing the stateless component to stateful or class-based component to use refs? Is it a recommended approach OR if it's only about refs we can use the old native approach of document refs or Jquery of getting an element reference.
Will changing of stateless to stateful component just for using refs and not any of the lifecycle methods are considered as best practice?
As far as I'm aware there is no real tradeoff when converting a stateless component to a stateful component, performance-wise at least (the following article outlines some findings with regards to this). Although you could go ahead an retrieve the DOM element by using document.getElementId or some other native solution, it is generally better to use refs since it's more inline with React's way of doing things (a more detailed Stack Overflow response and thread discussing this you can find here.
In case you are using refs to get an reference to DOM element when some kind of event is triggered, you could also retrieve the DOM node from the event itself without using any refs.
There is nothing forcing you to implement the life cycle hooks, even if you would convert your component to a class based one. Assuming the performance difference is minor it would be appropriate to convert a stateless functional component to a class based stateful component if you have an obvious use case where you want to use ref, although in most cases you could probably get away with using event handlers instead.
If you don't want to convert you functional component to a class based one, you could also use the useRef hook, which would allow you to use refs in your functional component without having to convert to a class based component (since React 16.8).
Related
I'm struggling about what may be a good way to implement components in React with a good coding pattern.
Normally I know the idea of presentational and container components: the presentational only shows html and receive everything from props (data and callbacks); the container orchestrate the presentationals retrieving and mutating data and passing it to them by props.
Now I'm using redux with redux toolkit and rtk query, with hooks.
Following that approach, the container component should be the only one allowed to useSelector and useDispatch and useQuery. But I find a lot easier and cleaner allowing the presentationals to select and fetch and dispatch what they really need, instead of making a giant container component which manage all the data for its children with a huge list of state and fetch access. This is true especially for lists, where it is a lot easier and cleaner just letting each child to retrieve its own data (fetched or from state), or for deeply nested presentationals.
However I'm mixing up container components with fake presentationals which anyway retrieve something when it is easier and true presentationals maybe for general and totally reusable components. Also the components tree is very messy (like container->fake presentational->container->fake presentational->true presentational->true presentational ...).
At the end I feel like I don't have good rules and the code is messed up.
Are container and presentation components still a good coding style which follows a best practice pattern but in the world of hooks and redux?
The React Container Pattern advocated by Dan Abramov has for all intents and purposes been deprecated since the introduction of React hooks in 2018.
See Dan's blog entry Presentational and Container Components from 2015.
His update from 2019:
Update from 2019: I wrote this article a long time ago and my views
have since evolved. In particular, I don’t suggest splitting your
components like this anymore. If you find it natural in your codebase,
this pattern can be handy. But I’ve seen it enforced without any
necessity and with almost dogmatic fervor far too many times. The main
reason I found it useful was because it let me separate complex
stateful logic from other aspects of the component. Hooks let me do
the same thing without an arbitrary division. This text is left intact
for historical reasons but don’t take it too seriously.
With the advent of React hooks the distinction between "smart" and "dumb" components, and "container" and "presentational" components, was all but eliminated.
The common pattern and "best practice" now is to write React Function components and just use the React hooks. In the case of using Redux and React-Redux, the useDispatch and useSelector hooks instead of the connect Higher Order Component. I've not gone out of my way to write a React Class component or split my code between "presentation" and "container" since the advent of React hooks.
My rule of thumb is to do it all in one component. Then as you create more and more components you'll see patterns start to emerge. So instead of copying and pasting code from component to component you can make a presentational component that takes in props for what to render. Some of those props can even be what to do when a button is clicked or a box is checked.
Overall your presentational components will end up resembling something like one of the various react js ui frameworks out there such as https://mui.com/
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.
I am not an expert in react so I am a little confused but since the introduction of react hooks. when do you use class components instead of functional components?
I would use class when there is something that functional components can't implement like state or lifecycle methods, waitttttttttttttttttt...
Since hooks have the state and lifecycle methods you don't need classes anymore :)
Your typical lifecycle methods have been replaced with useEffect, which reduces the amount of code you have significantly. You don't need to define multiple methods (componentDidMount, componentDidUpdate, etc) when you can use a single hook to take care of them all.
The other advantage is that they can start with much less boilerplate code than their class equivalent, and scales much better considering you don't need to replace multiple methods when reworking features in such a component.
The main reason you can still use classes is because there's no reason to remove them - they're still a core part of what React is and how it works. Hooks are newer and follow a completely different design approach to what everyone already knows. They're completely compatible with one another.
FOr example I have one parent component ( i'll call it animal)
and several child components (dog, cat, horse) and child's child components (Collie, English Foxhound, Fox Terrier, German Shepherd Dog). If i wanna send a function from animal to Collie, i have to send this function to Dog component and from Dog to Collie and only after 2 props i will be able to use this function in Collie component. Is there any better approch to send a function from animal directly to Collie ?
As mentioned by others on top the new Context API that was introduced in the new versions of react maybe different in react versions and still not recommended for just avoid passing props a fewer levels down in the component tree.
The component composition is a better option if you don't want to use redux which maybe complex for less usage like this example.
https://reactjs.org/docs/context.html#before-you-use-context
You basically create your parent component in this case <Animal/> to expected children nodes, <Dog />as well to expect children then you can later on pass it <Collie /> with the props.
Use the Context API.
Read more at the official docs : https://reactjs.org/docs/context.html
Basically, you define a context value and pass it with a Provider, which can be accessed by any node within the child tree.
Do note that the Context API is different for different versions of React and may change in future. You may also use Redux and react-redux for state management which would be internally using the context api.
You can use React Context API which is now official. More information as to how to use this can be found here - https://hackernoon.com/how-to-use-the-new-react-context-api-fce011e7d87
I would recommend to take a look at React "Component Composition" pattern (docs: https://reactjs.org/docs/composition-vs-inheritance.html). It is pretty straightforward and doesn't have a reusability issue that sometimes might occur in with React Context.
Ta-ta
Directly add a clickListener to component
<Grid onClick={this.state.event}/>
Set a ref then add clickListener
componentDidMount() {
ReactDOM.findDOMNode(this.refs.grid).addEventListener('click', this.state.event);
}
componentWillUnmount() {
ReactDOM.findDOMNode(this.refs.grid).removeEventListener('click', this.state.event);
}
<Grid fluid ref="grid"/>
Check please React documentation
Refs: https://reactjs.org/docs/refs-and-the-dom.html
Synthetic events: https://reactjs.org/docs/events.html
With refs you work with so-called uncontrolled components with browser-specific event data. You should be careful with refs, because you work with DOM element directly and it might lead to side effects in conjuction with React component's lifecycle. Some examples to use refs might be handling focus, text selections, custom formatting and cursor positioning in form inputs, integration of non-React 3rd-party libraries etc. Usually libraries like redux-form use refs heavily.
React's way with onClick (controlled components) provides cross-browser synthetic event data. React is smart enough and it uses only a single instance of event data to save memory. It is recommended to use controlled components to allow React fully control your components to avoid unintended behaviours, unless refs are explicitly needed.
If you develop some library to work with i.e. form elements, then using refs could be your convention.
String refs are deprecated in react 16.3 and refs are used mainly for the purpose of managing custom components and managing events like focus and selection. Use of refs is just an escape mechanism as it doesn't follow the conventional flow of parent-child hierarchy in react. Also, refs don't work for functional components, unless you are just accessing the Dom elements alone.
Read the don't overuse refs blog in react:
https://reactjs.org/docs/refs-and-the-dom.html
Maintaining single source of Truth for child components:
https://reactjs.org/docs/lifting-state-up.html