Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Direct call of a functional component

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?

like image 871
Estus Flask Avatar asked Aug 27 '18 21:08

Estus Flask


People also ask

How do you call a functional component?

To answer, it is as simple as creating a function returning an HTML-like syntax. import React from 'react'; function Counter({n}) { return ( <div>{n}</div> ); } export default Counter; Now let's see what happened in the code above. Counter is a function that transforms a number into HTML.

Can we call a component as a function?

Function and Class Components This function is a valid React component because it accepts a single “props” (which stands for properties) object argument with data and returns a React element. We call such components “function components” because they are literally JavaScript functions.

What is a functional component?

A functional component is just a plain JavaScript pure function that accepts props as an argument and returns a React element(JSX). A class component requires you to extend from React. Component and create a render function which returns a React element. There is no render method used in functional components.


1 Answers

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'));

live at: https://stackblitz.com/edit/react-bpqicw

like image 63
marzelin Avatar answered Oct 06 '22 16:10

marzelin