Stateless functional component is just a function that receives props
and returns React element:
const Foo = props => <Bar />;
This way <Foo {...props} />
(i.e. React.createElement(Foo, props)
) in parent component could be omitted in favour of calling Foo
directly, Foo(props)
, so React.createElement
tiny overhead could be eliminated, yet this isn't necessary.
Is it considered a bad practice to call functional components directly with props
argument, and why? What are possible implications of doing this? Can this affect the performance in negative way?
My specific case is that there's some component that is shallow wrapper over DOM element because this was considered a good idea by a third party:
function ThirdPartyThemedInput({style, ...props}) { return <input style={{color: 'red', ...style}} {...props} />; }
Here's a demo that shows this case.
This is widely accepted practice but the problem with it is that it's impossible to get ref
of wrapped DOM element from stateless function, so the component uses React.forwardRef
:
function withRef(SFC) { return React.forwardRef((props, ref) => SFC({ref, ...props})); // this won't work // React.forwardRef((props, ref) => <SFC ref={ref} {...props } />); } const ThemedInput = withRef(ThirdPartyThemedInput);
This way it can be used as:
<ThemedInput ref={inputRef} /> ... inputRef.current.focus();
The obvious downside I'm aware of is that withRef
requires a developer to be aware of wrapped component implementation, which isn't a usual requirement for HOCs.
Is it considered a proper approach in a situation like described above?
2 Answers
Answers 1
I don't think there's anything wrong with calling Stateless Functional Component directly. As you said it's even one tiny overhead eliminated. As to the possible implications, it would be bold to say that there are none implications and there will be none implications in the future because this is a really rare way of using SFC's. But everything points to conclusion that there shouldn't be any implications (it's just one function call less).
Anyway, below I'd like to present another way of doing this using findDOMNode
instead of refs:
I've created Focus
component that is really convenient to use but needs to be initialized first (since we need a way to trigger focus outside props since a component may be rerendered with the same props):
// focus.js import React from "react"; import { findDOMNode } from "react-dom"; export default function createFocus() { class Focus extends React.Component { componentDidMount() { Focus.now = () => { findDOMNode(this).focus(); } } render() { return this.props.children; } } return Focus; }
// index.js import React, { Component } from 'react'; import { render } from 'react-dom'; import createFocus from './focus'; const Focus = createFocus(); import { ThirdPartyThemedInput } from './third-party-lib'; function App() { return ( <div> <button onClick={() => Focus.now()}>Proceed with form</button> <Focus> <ThirdPartyThemedInput placeholder="Fill me" /> </Focus> </div> ); } render(<App />, document.getElementById('root'));
Answers 2
Functional components are very useful when you don't need to use any of the lifecycle method or don't need to update the component state. As far as you don't need to them, you're good and yet best to go with stateless component.
This will not hit the performance issue but gain the profit regarding its performance because we're just simply using function to render the component and not caring for its update, mounts, receive props, etc. But still there's no 100% gain using stateless component because react internally use class to render them.
This post will also guide which one to choose between statefull component and stateless component.
Further, you can not only receive the props but can also receive the ref:
const stateless = (props, ref) => <ReturnComponent {...props} ref={ref} />
Okay, let me refine my statement. Most of the blogs and even the docs states that stateless component don't have ref. Here are a few Q/A prepared regarding this issue:
Do I need to use statefull component just to use ref?
No. I already mentioned that we must require the class based component if we have to work with component state or hook some lifecycle method.
How can I create ref in stateless component?
const stateless = () => { // we can't do this.myRef = React.createRef() // so, let's create an object const RefObj = {} // now, create ref in {RefObj} RefObj.myRef = React.createRef() return <input type="text" ref={myRef} /> }
0 comments:
Post a Comment