1

As part of my React app, arrow function ContainerCookiesPolicy calls arrow function LogInTitleTest (and some others).

export default class MyClass extends React.Component {
    constructor(props) {
        super(props);
        this.state = {};
    }

    ContainerCookiesPolicy = () => {
        if (window.localStorage.getItem('CookiesAgreed') !== 'true') {
            return (
                <div className='ContainerCookiesPolicy'>
                    <this.LogInTitleTest/>
                    {/*Some other functions*/}
                </div>
            )
        } else {
            return null;
        }
    }

    LogInTitleTest = () => {
        return  (
            <span className='Log_in_title_text'>{'Text'}</span>
        );
    }

render() {
         <this.ContainerCookiesPolicy/>
         {/*Some other functions*/}
    }
}

If I execute this code, this is, function ContainerCookiesPolicy calls function LogInTitleTest, React will not render anything at all (like it does when your function/object returns null) and will give the error Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined.. However, if instead I copy and paste the content of LogInTitleTest inside ContainerCookiesPolicy like this:

ContainerCookiesPolicy = () => {
        if (window.localStorage.getItem('CookiesAgreed') !== 'true') {
            return (
                <div className='ContainerCookiesPolicy'>
                    <span className='Log_in_title_text'>{'Text'}</span>
                    {/*Some other functions*/}
                </div>
            )
        } else {
            return null;
        }
    }

it will actually render the entire page with the word Text on it.

Further considerations:

  1. If my function LogInTitleTest contains <div> instead, it will not render the page either; if the <div> are contained on function ContainerCookiesPolicy, it will render. Same thing if instead of {'Text'} I just have Text.
    LogInTitleTest = () => {
        return  (
            <div className="Log_in_title_container">
                <span className='Log_in_title_text'>{'Text'}</span>
            </div>
        );
    }
  1. If I change function LogInTitleTest to return null, the situation will remain exactly the same:
    LogInTitleTest = () => {
        return  null;
    }
  1. I'm using AWS Amplify to render the page. On WebStorm on localhost, I did not observe this weird behaviour.

  2. I tested the original function LogInTitleTest on another portion of code and it was working as expected. Hence the issue must be with ContainerCookiesPolicy.

Any idea why this is happening? Any help would be appreciated!

Thanks in advance

MartinHN
  • 124
  • 2
  • 9

1 Answers1

2

You shouldn't be referencing the component as <this.LogInTitleTest />. It should be <LogInTitleTest />.

Also be careful of the order you're defining functional components if they're in a single file. As described in this question, arrow functions are evaluated top-down.

    const LogInTitleTest = () => {
        return  (
            <span className='Log_in_title_text'>{'Text'}</span>
        );
    }

    const ContainerCookiesPolicy = () => {
        if (window.localStorage.getItem('CookiesAgreed') !== 'true') {
            return (
                <div className='ContainerCookiesPolicy'>
                    <LogInTitleTest />
                    {/*Some other functions*/}
                </div>
            )
        } else {
            return null;
        }
    }

EDIT: updates based on updated question

Now that you've updated the example it's clear you're using a class component. To render blocks of JSX within a class component you typically call the functions as functions rather than as components.

Also note the render function in your example isn't currently returning anything.

export default class MyClass extends React.Component {
    constructor(props) {
        super(props);
        this.state = {};
    }

    renderContainerCookiesPolicy = () => {
        if (window.localStorage.getItem('CookiesAgreed') !== 'true') {
            return (
                <div className='ContainerCookiesPolicy'>
                    {this.renderLogInTitleTest()}
                    {/*Some other functions*/}
                </div>
            )
        } else {
            return null;
        }
    }

    renderLogInTitleTest = () => {
        return  (
            <span className='Log_in_title_text'>Text</span>
        );
    }

    render() {
        return (
           {this.renderContainerCookiesPolicy()}
           {/*Some other functions*/}
        )
    }
}
j-petty
  • 2,668
  • 1
  • 11
  • 20
  • thanks for your answer! Though it did not help much, my functions are always declarative functions, so it does not play a role if I define them before/after calling them. Also, trying to define them as expression functions (const declaration) made the code fail. And removing the "this" from the function call also made it to fail. Note all functions are inside a React component and I'm passing the state to them, hence that would not work. – MartinHN Jul 26 '21 at 08:38
  • It's not clear based on the example provided what `this` is bound to. Are your functions defined in a class component? If so please include this detail in the question because it obviously influences the relevant answers. – j-petty Jul 26 '21 at 10:36
  • Thank you, @j-petty! Just updated the question with the class React.component. I think it should be better now? Otherwise, please let me know – MartinHN Jul 26 '21 at 11:25
  • @MartinHN I've updated my answer based on the additional information. – j-petty Jul 26 '21 at 23:39
  • Thanks a lot, @j-petty! This has solved my problem, I have already learnt my lesson. I guess WebStorm (my IDE) is "helping" me by reading all function used as components as functions themselves. Really appreciate you took the time to help me out :) Also correct about not rendering: it was only a quick mock to show I was using a class component. – MartinHN Jul 27 '21 at 00:27
  • No worries glad it was helpful! – j-petty Jul 27 '21 at 00:38