Home > Software design >  To create a Function Component with Hooks, why do I have to use JSX, and not just a function call?
To create a Function Component with Hooks, why do I have to use JSX, and not just a function call?

Time:04-04

In React Typescript, let's say I have this function component:

import React, { useEffect } from 'react';
import ReactDOM from 'react-dom';

interface testFCProps {
  var1: string;
  var2: string;
  var3?: string;
}
const TestFC: React.FC<testFCProps> = (props: testFCProps) => {
  useEffect(() => {
    console.log('testFC use effect');
  });
  return (
    <div>
      here are my vars: {props.var1}, {props.var2}, {props.var3}.
    </div>
  );
};

I can display it in a React app, using JSX syntax:

const displayDiv = <TestFC var1="hello" var2="there" var3="general-kenobi" />;


ReactDOM.render(
  <React.StrictMode>{displayDiv}</React.StrictMode>,
  document.getElementById('root')
);

Result in-browser: here are my vars: hello, there, general-kenobi.

However, if I try to create displayDiv using function syntax, like so:

const displayDiv = TestFC({
  var1: 'hello',
  var2: 'there',
  var3: 'general-kenobo',
});

I get in-browser Error: Invalid hook call. I am pretty sure I am using useEffect hook properly here. If I comment it out, there is no error, so I don't think there is an issue inherent to creating function components with a function call.

Why is the creation of a function component using a function, and hooks, appear to be in conflict?

CodePudding user response:

Normally, function components get called by react in the middle of the rendering process. In your case, you're calling the function at a time when rendering is not taking place, which is causing the error. React has to do a bit of setup work before hand to let hooks like useEffect do their thing, and that hasn't happened for your case.

If you just want to avoid the JSX syntax, you can do that, but you need to use equivalent code. The equivalent of <TestFC var1="hello" var2="there" var3="general-kenobi" /> isn't the function call you tried, but rather this:

const displayDiv = React.createElement(TestFC, {
  var1: 'hello',
  var2: 'there',
  var3: 'general-kenobo',
})

createElement returns an object describing what you want to be on the page, but doesn't actually call TestFC yet. Later on, when rendering happens, react will look at the displayDiv object, set things up, and call the component function for you.

  • Related