Ada
Ada

Reputation: 569

How do I return two functions in a function that renders as two components in react instead of the second function overwriting the first

I am using a conditional rendering to render different elements in my react header based on url or if a user is logged in. In my default return I want to render two buttons side by side instead only the second button appears. How do I fix this?

const NavHeader = () => {
    const { location } = useSelector(state => state.router);
    const { authenticated } = useSelector(state => state.signIn);

    const menuItem = (linkPath, text, type) => (
        <Item className="header-item">
            <Button type="primary" ghost={type}>
                <Link to={linkPath}>
                    {text}
                </Link>
            </Button>
        </Item>
    );

    const renderMenuItem = ({ pathname }) => {
        if (pathname === '/signup') {
            return menuItem('/signin', SIGNIN, false);
        }
        if (pathname === '/signin') {
            return menuItem('/signup', SIGNUP, true);
        }
        if (authenticated) {
            return menuItem('/dashboard', GO_TO_DASHBOARD, false);
        }
        return (
            menuItem('/signin', SIGNIN, false)
            && menuItem('/signup', SIGNUP, true)
        );
    };

    return (
        <Header>
            <Link to="/" className="left-menu">
                <img src={Logo} height="60px" alt="NeoNatar Logo" />
            </Link>
            <Menu className="right-nav" mode="horizontal">
                {renderMenuItem(location)}
            </Menu>
        </Header>
    );
};


Upvotes: 3

Views: 1563

Answers (1)

T.J. Crowder
T.J. Crowder

Reputation: 1074295

You can return an array or a fragment containing both.

Array:

return [
    menuItem('/signin', SIGNIN, false),
    menuItem('/signup', SIGNUP, true)
];

Fragment:

return (
    <React.Fragment>
        {menuItem('/signin', SIGNIN, false)}
        {menuItem('/signup', SIGNUP, true)}
    </React.Fragment>
);

Another way to use fragment in modern versions of Babel:

return (
    <>
        {menuItem('/signin', SIGNIN, false)}
        {menuItem('/signup', SIGNUP, true)}
    </>
);

What you had didn't work because the result of the && operator is the value of just one of its operands. It evaluates its left-hand operand and, if that value is falsy, takes that value as its result; otherwise, it evaluates its right-hand operand and takes that value as its result. In your case, since menuItem returns an object, it's truthy, so the second menuItem call was done and its result was the result of the && expression.

Upvotes: 1

Related Questions