render two components in react conditional - javascript

currently working on a simple navbar component. The following is my code:
{isLoggedIn ?
<Navbar.Brand ><Link to="/" style={{ textDecoration: 'none' }} onClick={() => dispatch(logoutUser())}>Logout</Link></Navbar.Brand>
:
<Navbar.Brand ><Link to="/registration" style={{ textDecoration: 'none' }}>Register</Link></Navbar.Brand>
<Navbar.Brand ><Link to="/login" style={{ textDecoration: 'none' }}>Login</Link></Navbar.Brand>
}
When the user is logged in, I want a logout button to appear, and when they are not logged in I want both register and login buttons to appear. But I cannot do both at the same time when isLoggedIn is false. Any way to do this?
Thank you!

{isLoggedIn ? <Navbar.Brand ><Link to="/" style={{ textDecoration: 'none' }} onClick={() => dispatch(logoutUser())}>Logout</Link></Navbar.Brand>
: <div>
<Navbar.Brand ><Link to="/registration" style={{ textDecoration: 'none' }}>Register</Link></Navbar.Brand>
<Navbar.Brand ><Link to="/login" style={{ textDecoration: 'none' }}>Login</Link></Navbar.Brand>
</div>
}
Edit: as suggested below, it is also possible to wrap between fragments.

Related

Antd card loading is not working properly

I'm using antd card component to display the card and loading is not working, I gave the loading based on the api response, i got the correct response but the loading is not working for me.... if i set the loading value to true it is working fine but it is not working while i'm passing the data.
useEffect(() => {
let keys = [{ key: "get_search_records", loading: true }];
dispatch(
dynamicRequest(keys, get_search_records_query, {
searchString: state,
})
);
}, [state]);
I'm getting data and changing the loading here and it is working fine, the loading also changes perfectly but it is not reflecting in the card component
<Box>
<HStack marginLeft={10} space={20} flexWrap={'wrap'}>
{items?.map((item, index) => (
<VStack marginTop={"30px"} space={10} flexWrap={"wrap"}>
<Card
loading={loading}
hoverable
style={{ height: 430 ,width: 250, borderRadius: "10px", marginTop:30, marginBottom: 30 }}
cover={
<HStack>
<Box width={"50%"}>
<div class="card_div">
<div style={{marginTop:"5px"}}>
<Text color={"white"} alignItems="center" marginLeft={"17px"} marginTop={"7px"} >
Hot
</Text>
</div>
</div>
</Box>
<Box flexDirection="row-reverse" marginTop={"-30px"} marginRight={"10px"} padding={"5px"}>
<Typography.Link onClick={handleAddCart}>
<Tooltip className="tooltip-wishlist" color=" #3BB77E" title="Add to wishlist" placement="bottom">
<AiOutlineHeart size={"25px"}/>
</Tooltip>
</Typography.Link>
</Box>
</HStack>
}
>
<Box alignContent={"center"} height="170px">
{/* <AspectRatio w="100%" ratio={16/9}> */}
<Image
alt="Image"
src={item?.vendor_product?.product?.gallery?.[0]}
// width="90%"
preview={false}
/>
</Box>
<Box alignContent={"center"}>
<Text bold> </Text>
<VStack space={1.5}>
<Box height="130px">
<Text color={"#adadad"}>
{item.vendor_product.product.category.name}
</Text>
<Text onPress={handleClick} onMouseOver={mouseOver} onMouseOut={MouseOut} bold>{item.name} </Text>
<Rating count={item?.product_rating?.[0]?.rating}/>
<Text onPress={handleTextPress}>
By <span style={{ color: "#22c55e" }} onMouseOver={mouseOverVendor} onMouseOut={mouseOutVendor} >Theni FBO</span>
</Text>
</Box>
<HStack justifyContent="space-between">
{item.discount && (
<Text color="green.500">₹ {item.base_price}</Text>
)}
<Text strikeThrough color="green.500">
₹ {item.selling_price}
</Text>
<Button onClick={addCart} className="cart-btn" icon={<BsCart3 />}>
Add
</Button>
</HStack>
</VStack>
</Box>
</Card>
</VStack>
))}
</HStack>)}
</Box>
this is my antd card code... anyone please tell me why the loading is not working properly.

sidebar menu with dropdown in react js

i am trying to create a sidebar with drop down
like this example in react js
https://www.w3schools.com/howto/howto_js_dropdown_sidenav.asp
i was able to design it using react the issue is that when i click on a inner li
the dropdown closes i dont want it to close
this.state = { isOpen: false, }
Clickhandler() {
this.setState({ isOpen: !this.state.isOpen });
}
<li style={styles.listItem}
onClick={this.Clickhandler}
className={this.state.isOpen ? "admintabs" : ""}
>
<div>
<FontAwesomeIcon
icon={faHistory}
style={{ marginRight: "1rem" }}
/>
</div>
<div> Internal users</div>
<div>
{" "}
<FontAwesomeIcon icon={faCaretDown} />
</div>
</li>
{this.state.isOpen ? (
<>
<NavLink
to="/admin/saler"
activeClassName="active3"
onClick={this.Clickhandler}
>
<li style={styles.listItem}>
<div>
<FontAwesomeIcon
icon={faCube}
style={{ marginRight: "1rem" }}
/>
</div>
<div> saler</div>
</li>
</NavLink>
<NavLink
to="/admin/con"
activeClassName="active3"
onClick={this.Clickhandler}
>
<li style={styles.listItem}>
<div>
<FontAwesomeIcon
icon={faBriefcaseMedical}
style={{ marginRight: "1rem" }}
/>
</div>
<div> Con</div>
</li>
</NavLink>
</>
) : null}
my code is too big so i added in codesand box
https://codesandbox.io/s/stupefied-hooks-9qm66s?file=/src/App.js

When I add <Link></Link> component Layout's SelectedKeys is not working

Here is my *Navbar
import React, { useState } from "react";
import { Layout, Menu } from "antd";
import {
MenuUnfoldOutlined,
MenuFoldOutlined,
UserOutlined,
VideoCameraOutlined,
UploadOutlined,
} from "#ant-design/icons";
import { Link } from "react-router-dom";
const { Header, Sider, Content } = Layout;
const Navbar = (props) => {
const [collapsed, setCllapsed] = useState(false);
const toggle = () => {
setCllapsed(!collapsed);
};
return (
<div>
<Layout id="components-layout-demo-custom-trigger">
<Sider trigger={null} collapsible collapsed={collapsed}>
<div className="logo" />
<Menu theme="dark" mode="inline" defaultSelectedKeys={["1"]}>
<Menu.Item key="1" icon={<UserOutlined />}>
<Link style={{ textDecoration: "none" }} to="/">
Dashboard
</Link>
</Menu.Item>
<Menu.Item key="2" icon={<UserOutlined />}>
<Link style={{ textDecoration: "none" }} to="/groups">
Groups
</Link>
</Menu.Item>
<Menu.Item key="3" icon={<VideoCameraOutlined />}>
<Link style={{ textDecoration: "none" }} to="/tutors">
Tutors
</Link>
</Menu.Item>
<Menu.Item key="4" icon={<UserOutlined />}>
<Link style={{ textDecoration: "none" }} to="/students">
Students
</Link>
</Menu.Item>
</Menu>
</Sider>
<Layout className="site-layout">
<Header className="site-layout-background" style={{ padding: 0 }}>
{React.createElement(
collapsed ? MenuUnfoldOutlined : MenuFoldOutlined,
{
className: "trigger",
onClick: toggle,
}
)}
</Header>
<Content
className="site-layout-background"
style={{
margin: "24px 16px",
padding: 24,
minHeight: 280,
}}
>
{props.children}
</Content>
</Layout>
</Layout>
</div>
);
};
export default Navbar;
In this example I was using <Menu.Item></Menu.Item> component from antd . But it stopped working when clicked once. It changed onclick function. After adding from react-router-dom, I am having trouble with SelectedKeys of Antdesign's Layout. Before Link component of react-router-dom selectedKeys was working when you click one time, but after adding Link component, SelectedKeys is working when double clicked. How can I solve it? I need this should work once. Anyone can help me?

I want to show and hide a form on toggle of a radio button in React js . Im trying how to use react hooks to hide or show a component on onChange even

Now i have used state hook to hide the Form when the page loads. And upon the click or toggle of the radio I'm able to show the Form, But if i toggle the radio again, the form is not hiding.
This is what i have implemented:
const WelcomeTab = () => {
const [toggle, settoggle] = useState(false);
return (
<React.Fragment>
<Tab.Pane
style={{
borderRadius: '7px',
padding: '30px',
}}
attached={false}
>
<Grid>
<Grid.Row>
<Grid.Column floated="left" width={8}>
<Header
style={{
fontSize: '18px',
fontFamily: 'Nunito-Regular',
color: '#4F4F4F',
}}
>
Welcome Screen
</Header>
</Grid.Column>
<Grid.Column floated="right" width={4}>
<Header
as="h4"
style={{
display: 'flex',
justifyContent: 'space-around',
marginLeft: '30px',
}}
>
Customize
<Radio toggle onChange={() => settoggle({ toggle: !toggle })} />
</Header>
</Grid.Column>
</Grid.Row>
</Grid>
{toggle ? (
<Form style={{ paddingTop: '20px' }}>
<Form.Field>
<label style={lableStyle}>Title</label>
<input style={{ marginBottom: '20px' }} />
<label style={lableStyle}>Message</label>
<TextArea />
</Form.Field>
</Form>
) : null}
</Tab.Pane>
</React.Fragment>
);
};
const lableStyle = {
fontFamily: 'Nunito-Regular',
fontWeight: 400,
color: '#4F4F4F',
fontSize: '15px',
display: 'inline-block',
marginBottom: '10px',
};
export default WelcomeTab;
try to add useEffect hook along with change like below,
you no longer need to {} this is old syntax of setState, using hooks we directly make the changes, hope this helps
useEffect(()=>{},[toggle])
replace this wrong syntax code, i can see its not json its boolean value
<Radio toggle onChange={()=>settoggle({toggle: !toggle})}/>
as this is old syntax not work with hooks, try to implment this instead,
<Radio toggle onChange={()=>settoggle(!toggle)}/>

Show length of an array based on what is left in array after its sliced

I have a react component that upon clicking showMore. it will load more comments. The issue im facing is that
View {showMore} More Comments
is not showing the items that are left in the array. Currently there are 7 comments in an array, and if you click show more, it will initially read show 3 more, but when i click again it says show 6 more. when it should be a lesser number than 6. It should be like show 2 more, etc. I'm quite confused on how to go about writing this logic.
What am i doing wrong
CommentList.tsx
import React, { Fragment, useState } from "react";
import Grid from "#material-ui/core/Grid";
import List from "#material-ui/core/List";
import Typography from "#material-ui/core/Typography";
import CommentItem from "./../commentItem/CommentItem";
import moment from "moment";
import OurLink from "../../../common/OurLink";
import OurSecondaryButton from "../../../common/OurSecondaryButton";
import OurModal from "../../../common/OurModal";
.....
function CommentList(props: any) {
const [showMore, setShowMore] = useState<Number>(3);
const [openModal, setOpenModal] = useState(false);
const [showLessFlag, setShowLessFlag] = useState<Boolean>(false);
const the_comments = props.comments.length;
const inc = showMore as any;
const showComments = (e) => {
e.preventDefault();
if (inc + 3 <= the_comments) {
setShowMore(inc + 3);
} else {
setShowMore(the_comments);
}
// setShowLessFlag(true);
};
........
const showMoreComments = () => {
return props.comments
.slice(0, showMore)
.sort((a, b) => a.id - b.id)
.map((comment, i) => (
<div key={i}>
<List style={{ paddingBottom: "20px" }}>
<img alt="gravatar" style={{ margin: "-10px 15px" }} src={comment.author.gravatar} width="30" height="30" />
<Typography style={{ display: "inline-block", fontWeight: 700, padding: "5px 0px" }} variant="h6" align="left">
{Object.entries(props.currentUser).length === 0 ? (
<Fragment>
<span style={{ cursor: "pointer", fontSize: "12px", fontWeight: isBold(comment) }} onClick={handleClickOpen}>
{comment.author.username}
</span>
{comment.userId === props.userId && <span style={{ fontSize: "12px" }}> (OP)</span>}
{openModal ? <OurModal open={openModal} handleClose={handleCloseModal} /> : null}
</Fragment>
) : (
<Fragment>
<OurLink
style={{ fontSize: "12px", fontWeight: isBold(comment) }}
to={{
pathname: `/profile/${comment.author.username}`,
}}
title={comment.author.username}
/>
{comment.userId === props.userId && <span style={{ fontSize: "12px" }}> (OP)</span>}
</Fragment>
)}
</Typography>
<div style={ourStyle}>
<CommentItem comment={comment} user={props.user} postId={props.postId} {...props} />
<Typography style={{ fontSize: "12px" }} variant="body1" align="left">
{moment(comment.createdAt).calendar()}
</Typography>
</div>
</List>
</div>
));
};
console.log(props.comments.slice(0, showMore).length);
return (
<Grid>
<Fragment>
<div style={{ margin: "30px 0px" }}>
<OurSecondaryButton onClick={(e) => showComments(e)} component="span" color="secondary">
View {showMore} More Comments
</OurSecondaryButton>
</div>
</Fragment>
{showLessFlag === true ? (
// will show most recent comments below
showMoreComments()
) : (
<Fragment>
{/* filter based on first comment */}
{props.comments
.filter((item, i) => item)
.sort((a, b) => b.id - a.id)
.slice(0, showMore)
.map((comment, i) => (
<div key={i}>
<List style={{ paddingBottom: "20px" }}>
<img alt="gravatar" style={{ margin: "-10px 15px" }} src={comment.author.gravatar} width="30" height="30" />
<Typography style={{ display: "inline-block", fontWeight: 700, padding: "5px 0px" }} variant="h6" align="left">
{Object.entries(props.currentUser).length === 0 ? (
<Fragment>
<span style={{ fontSize: "12px", cursor: "pointer", fontWeight: isBold(comment) }} onClick={handleClickOpen}>
{comment.author.username}
{comment.userId === props.userId && <span style={{ fontSize: "12px" }}> (OP)</span>}
</span>
{openModal ? <OurModal open={openModal} handleClose={handleCloseModal} /> : null}
</Fragment>
) : (
<Fragment>
<OurLink
style={{ fontSize: "12px", fontWeight: isBold(comment) }}
to={{
pathname: `/profile/${comment.author.username}`,
}}
title={comment.author.username}
/>
{comment.userId === props.userId && <span style={{ fontSize: "12px" }}> (OP)</span>}
</Fragment>
)}
</Typography>
<div style={ourStyle}>
<CommentItem comment={comment} user={props.user} postId={props.postId} {...props} />
<Typography style={{ fontSize: "12px" }} variant="body1" align="left">
{moment(comment.createdAt).calendar()}
</Typography>
</div>
</List>
</div>
))}
</Fragment>
)}
</Grid>
);
}
// prevents un-necesary re renders
export default React.memo(CommentList);
You want to show 3 more comments each time, or 1-2 items if there are less than 3 items left. So "View 3 More comments" if there are more than 3 left, or "View 1/2 More Comments" if there are only 1 or 2 left.
Or in other words cap the number of new comments shown at 3:
the minimum value of either 3 or (total number of comments - current shown comments = number of comments left).
View {Math.min(3, the_comments - inc)} More Comments

Categories