Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using React functional component as a Type

I am able to use a React class component (i.e. React.Component) as a Type but unable to use functional/stateless components. Here is an example:

import Footer from 'path/to/component/Footer';

interface ComponentProps {
    customFooter: (Footer)
}

class MyComponent extends React.Component<ComponentProps> {
    render() {
        return (
            <div>
                {this.props.customFooter}
            </div>
        );
    }
}

Footer.tsx

const Footer: React.StatelessComponent<{ children?: any }> = ({ children }) => (
    <footer>
        <div>
            {children}
        </div>
    </footer>
);

export default Footer;

The red underline is under the (Footer) and reads: Cannot find name 'Footer'.

I've discovered that if I use a React class component instead of a functional component, my issue goes away. Why is it that I cannot use a functional component and is there a way for me to do so?

like image 491
noblerare Avatar asked Jul 05 '18 15:07

noblerare


People also ask

Should you use React FC for typing React components?

The consensus in the React community now seems to be that, you should avoid using React. FC because it causes the component to implicitly take children . This means the component will accept children, even if they're not supposed to.

What is the type of React function component?

Functional Components — functions that return JSX. Can do more stuff with React Hooks. Class Components — classes that can manipulate state, props, and lifecycle methods. Pure Components — functional components that performs shouldComponentUpdate() automatically.

Is React FC deprecated?

From the sounds of things, it will eventually be deprecated in favor of the naming React. FunctionComponent once React 18 is released.

Is it better to use functional components React?

React recommends that Functional Components are used over classes, and even will throw warnings about a few Class Component lifecycle methods that are being deprecated.


1 Answers

Footer isn't a type it is only a variable, to get the type you could use typeof

const Footer: React.StatelessComponent<{ children?: any }> = ({ children }) => (
    <footer>
        <div>
            {children}
        </div>
    </footer>
);

interface ComponentProps {
    customFooter: typeof Footer    
}

then you can use it like this:

class MyComponent extends React.Component<ComponentProps> {
    render() {
        const {customFooter: CustomFooter} = this.props;
        return (
            <div>
                {<CustomFooter>footer children</CustomFooter>}
            </div>
        );
    }
}

const MainComponent = () => {
    return (<MyComponent customFooter={Footer}/>)
};

if you want to add an actual jsx element as value like this:

const MainComponent = () => {
    return (<MyComponent customFooter={<Footer>footer children</Footer>}/>)
};

then you need to set the type of customFooter to something like React.ReactNode:

interface ComponentProps {
    customFooter: React.ReactNode
}
like image 146
jmattheis Avatar answered Sep 29 '22 11:09

jmattheis