Select only a card at a time on click in reactjs - javascript

I have a react component which has some cards, When I click the plus icon in the card, it would expand and show some data for 30sec and then the data will disappear and on click it will reappear again, here is the component
import React from "react";
import { FaPlus } from "react-icons/fa";
import useTimeout from "../../../common/useTimeout";
import { Modal } from "../../../common/Modal";
import { ToggleState } from "../../../common/Toggle";
import { BsSearch } from "react-icons/bs";
import AdvancedFilter from "./AdvancedFilter";
export default function CitiesList({ cities }: { cities: any }): JSX.Element {
const [filter, setFilter] = React.useState("");
const [sortType, setSortType] = React.useState("");
const [selectedCity, setSelectedCity] = React.useState<any | null>(null);
console.log(filter);
const sorted = cities.sort((a: { name: string }, b: { name: any }) => {
const isReversed = sortType === "asc" ? 1 : -1;
return isReversed * a.name.localeCompare(b.name);
});
const onSort = (sortType: React.SetStateAction<string>) => {
console.log("changed");
setSortType(sortType);
};
const [showMeta, setShowMeta] = React.useState(false);
const handleClick = () => setShowMeta(true);
const getSelectedCity = (selectedCity: any) => {
setSelectedCity(selectedCity);
console.log("SELECTED CITY", selectedCity);
};
const [visible, setVisible] = React.useState(true);
const hide = () => setVisible(false);
useTimeout(hide, 30000);
console.log("CITIES", cities);
console.log({ selectedCity });
return (
<div style={{ marginTop: "3rem" }}>
<div
style={{
display: "flex",
justifyContent: "space-between",
alignItems: "center",
marginBottom: "20px",
}}
>
<div>List of cities</div>
<div style={{ display: "flex", alignItems: "center" }}>
<div style={{ marginRight: "1rem" }}>
<ToggleState
render={({ isOpen, open, close }) => {
return (
<>
<button
type="button"
className="btn btn-primary"
onClick={() => {
isOpen ? close() : open();
}}
>
Advanced Filter
</button>
<Modal
isActive={isOpen}
modalContentWidth={"30%"}
header={() => "Advanced Filter"}
close={() => close()}
renderBody={() => {
return <AdvancedFilter close={() => close()} />;
}}
></Modal>
</>
);
}}
/>
</div>
<div style={{ position: "relative", marginRight: "1rem" }}>
<input
type="text"
placeholder="Filter"
name="namePrefix"
style={{ padding: "0.35rem" }}
onChange={(e: any) => {
setFilter(e.target.value);
}}
/>
<div style={{ position: "absolute", top: "5px", right: "5px" }}>
<BsSearch size="16" />
</div>
</div>
<div style={{ width: "8rem" }}>
<div className="btn-group">
<button
type="button"
className="btn dropdown-toggle sort-button"
data-bs-toggle="dropdown"
aria-expanded="false"
>
{sortType === "asc"
? "Ascending"
: sortType === "desc"
? "Descending"
: "Select"}
</button>
<ul className="dropdown-menu sort-button">
<li>
<button
className="dropdown-item"
type="button"
onClick={() => onSort("asc")}
>
Ascending
</button>
</li>
<li>
<button
className="dropdown-item"
type="button"
onClick={() => onSort("desc")}
>
Descending
</button>
</li>
</ul>
</div>
</div>
</div>
</div>
<div>
<div>
<div className="row">
{cities &&
sorted.map((item: any, index: number) => (
<div className="col-lg-3" key={index}>
<div
className="card"
style={{
textAlign: "center",
display: "flex",
justifyContent: "center",
paddingBottom: "1rem",
marginBottom: "1rem",
marginRight: "1rem",
}}
>
<div className="card-body">
<h5 className="card-title">{item.name}</h5>
</div>
{visible && showMeta ? (
<div>
<p>Longitude: {item.longitude}</p>
<p>Latitude: {item.latitude}</p>
<p>Population: {item.population}</p>
{/* <p>Time Zone: America</p> */}
</div>
) : (
<div
onClick={() => {
handleClick();
getSelectedCity(item.id);
}}
style={{ cursor: "pointer" }}
>
<FaPlus size="18" />
</div>
)}
</div>
</div>
))}
</div>
</div>
</div>
<div
style={{ marginTop: "30px", display: "flex", justifyContent: "center" }}
>
{cities && cities.length > 10 ? (
<button className="secondary-button">Load More</button>
) : (
<p>There are no more cities</p>
)}
</div>
</div>
);
}
here is the useTimeout function
import { useEffect, useRef } from "react";
function useTimeout(callback: () => void, delay: number | null) {
const savedCallback = useRef(callback);
useEffect(() => {
savedCallback.current = callback;
}, [callback]);
useEffect(() => {
if (delay === null) {
return;
}
const id = setTimeout(() => savedCallback.current(), delay);
return () => clearTimeout(id);
}, [delay]);
}
export default useTimeout;
Now currently if I click on one card, all the cards opens and also after when the data disappears after 30sec it does not reappear on button click. I need to reload the page to do reappear data again.I need to solve 2 issues here: 1. how can I open one card only at a time on clicking on the icon, 2. how can I reappear data on button click without refreshing the page.

As I understand you, some information is
<p>Longitude: {item.longitude}</p>
<p>Latitude: {item.latitude}</p>
<p>Population: {item.population}</p>
You have global statement of showing this info for all cards. To reduce it, make new component which will have local state of this info:
import React from 'react'
const timeout = 15000
export const CityCard = ({item, visible, getSelectedCity}) => {
const [showMeta, setShowMeta] = React.useState(false)
const handleClick = React.useCallback(()=>{
setShowMeta(true)
setTimeout(()=>{
setShowMeta(false)
},timeout )
}, [showMeta])
return(
<div className="col-lg-3" key={index}>
<div
className="card"
style={{
textAlign: "center",
display: "flex",
justifyContent: "center",
paddingBottom: "1rem",
marginBottom: "1rem",
marginRight: "1rem",
}}
>
<div className="card-body">
<h5 className="card-title">{item.name}</h5>
</div>
{visible && showMeta ? (
<div>
<p>Longitude: {item.longitude}</p>
<p>Latitude: {item.latitude}</p>
<p>Population: {item.population}</p>
{/* <p>Time Zone: America</p> */}
</div>
) : (
<button
onClick={() => {
handleClick();
getSelectedCity(item.id);
}}
type='button'
disabled={showMeta}
style={{ cursor: "pointer" }}
>
<FaPlus size="18" />
</button>
)}
</div>
</div>
)
}
At the end, add this component to the CityList

Related

I am trying to use a global state through the Context API but it does not read me a "Theme" state that I have created

it gives me this error
App.js:14 Uncaught TypeError: Cannot destructure property 'theme' of '(0 , react__WEBPACK_IMPORTED_MODULE_8__.useContext)(...)' as it is undefined
[IN CART.JS I CAN EASILY TAKE MY ADDTOCART STATE, BUT IN APP.JS IT DOESN'T LET ME TAKE THE "THEME" STATE AND I DON'T KNOW WHAT WILL BE THE REASON]
[CARTCONTEXT.JS]
import React, { createContext, useState } from "react";
export const CarritoContext = createContext();
export default function CartContext({ children }) {
const [addToCarrito, setAddToCarrito] = useState([]);
const [theme, setTheme] = useState("light");
async function addItem(item, quantity) {
const foundProdIndex = await addToCarrito.findIndex(
(product) => product.item.id === item.id
);
if (foundProdIndex === -1) {
setAddToCarrito([...addToCarrito, { item, quantity }]);
}
if (quantity === 0) {
setAddToCarrito([...addToCarrito]);
}
}
function clear() {
setAddToCarrito([]);
}
function removeItem(itemId) {
const newItems = addToCarrito.filter((item) => item.item.id !== itemId);
setAddToCarrito(newItems);
}
const toggleTheme = () => {
setTheme((prevTheme) => (prevTheme === "light" ? "dark" : "light"));
};
return (
<>
<CarritoContext.Provider
value={{
addToCarrito,
setAddToCarrito,
clear,
addItem,
removeItem,
theme,
toggleTheme,
}}
>
{children}
</CarritoContext.Provider>
</>
);
}
[APP.JS]
import "./App.scss";
import ItemDetailContainer from "./components/ItemDetailContainer/ItemDetailContainer";
import ItemListContainer from "./components/ItemListContainer/ItemListContainer";
import Navbar from "./components/Navbar/Navbar";
import { Routes, Route } from "react-router-dom";
import ItemList from "./components/ItemList/ItemList";
import NotFound404 from "./components/NotFound404/NotFound404";
import Cart from "./components/Cart/Cart";
import CartContext, { CarritoContext } from "./context/CartContext";
import React, { useContext } from "react";
function App() {
let { theme } = useContext(CarritoContext);
return (
<>
<CartContext>
<div className="App" id={theme}>
<Navbar />
<Routes>
<Route path="/carvel-ecommerce" element={<ItemListContainer />} />
<Route
path="/carvel-ecommerce/category/:id"
element={<ItemList />}
/>
<Route
path="/carvel-ecommerce/item/:id"
element={<ItemDetailContainer />}
/>
<Route path="/carvel-ecommerce/cart" element={<Cart />} />
<Route path="*" element={<NotFound404 />} />
</Routes>
</div>
</CartContext>
</>
);
}
export default App;
[CART.JS] (HERE THE CONTEXT WORKS FINE]
import React, { useContext } from "react";
import { Link } from "react-router-dom";
import { CarritoContext } from "../../context/CartContext";
import "./Cart.scss";
import { BsTrash } from "react-icons/bs";
import { MdOutlineCleaningServices } from "react-icons/md";
import { motion } from "framer-motion";
import { v4 as uuidv4 } from "uuid";
import { ReactComponent as Womens } from "../../assets/women-coat-svgrepo-com.svg";
import { ReactComponent as Hats } from "../../assets/accesory-hats-svgrepo-com.svg";
import { ReactComponent as Glasses } from "../../assets/glasses-svgrepo-com.svg";
import { ReactComponent as Jackets } from "../../assets/jacket-svgrepo-com.svg";
const Cart = () => {
let { addToCarrito } = useContext(CarritoContext);
let { clear } = useContext(CarritoContext);
let { removeItem } = useContext(CarritoContext);
const variants = {
hidden: { opacity: 0 },
visible: { opacity: 1 },
};
const totalPrice = addToCarrito
.map((product) => {
return product.item.price * product.quantity;
})
.reduce((item, qty) => item + qty, 0);
const pickData = addToCarrito.map((producto) => {
return (
<p key={uuidv4()}>
<small>
{producto.item.name}({producto.quantity}) :
<strong> ${producto.item.price * producto.quantity}</strong>
</small>
</p>
);
});
return (
<>
{addToCarrito.length > 0 ? (
addToCarrito.map((producto) => {
return (
<motion.div
initial="hidden"
animate="visible"
variants={variants}
key={uuidv4()}
>
<motion.div
initial="hidden"
animate="visible"
variants={variants}
className="container"
>
<motion.section
initial="hidden"
animate="visible"
variants={variants}
id="cart"
>
<motion.article
initial="hidden"
animate="visible"
variants={variants}
className="product"
>
<header>
<img
src={producto.item.imageUrl}
alt=""
style={{
backgroundColor: "white",
width: "100%",
height: "100%",
objectFit: "contain",
}}
/>
</header>
<div className="content">
<h1>
{producto.item.name}
<BsTrash
onClick={() => removeItem(producto.item.id)}
className="basurita"
/>
</h1>
{producto.item.category} | {producto.item.color}
<h5 style={{ marginTop: "10px" }}>
<span>
<small className="initial-price">
<span
style={{
backgroundColor: "#00640a",
height: "120px",
}}
>
     
</span>{" "}
Initial price{" "}
</small>
</span>
</h5>
<h5>
<span>
<small className="final-price">
<span
style={{
height: "120px",
backgroundColor: "yellow",
}}
>
   
</span>
<span
style={{
height: "120px",
backgroundColor: "black",
}}
>
   
</span>{" "}
Final price{" "}
</small>
</span>
</h5>
</div>
<footer className="content">
<span className="qt">
<strong>Qty: </strong> {producto.quantity}
</span>
<h2 className="full-price">
${producto.item.price * producto.quantity}
</h2>
<h2 className="price">${producto.item.price}</h2>
</footer>
</motion.article>
</motion.section>
</motion.div>
</motion.div>
);
})
) : (
<>
<h1
style={{
textAlign: "center",
fontSize: "42px",
borderBottom: "2px solid #ececec",
}}
>
The cart is empty... Start enjoying our products and visit us again
</h1>
<Link to={`/carvel-ecommerce`} className="button-backhome">
GO BACK TO HOME
</Link>
<div
style={{
display: "flex",
textDecoration: "none",
flexDirection: "column",
alignItems: "flex-end",
}}
>
<Link
to={"/carvel-ecommerce/category/Glasses"}
style={{
display: "flex",
flexDirection: "row",
alignItems: "center",
justifyContent: "space-between",
}}
>
<span>Glasses</span>{" "}
<span>
<Glasses className="iconpower" />
</span>
</Link>
<Link
to={"/carvel-ecommerce/category/Hats"}
style={{
display: "flex",
flexDirection: "row",
alignItems: "center",
justifyContent: "space-between",
}}
>
<span>Hats</span>{" "}
<span>
<Hats className="iconpower" />
</span>
</Link>
<Link
to={"/carvel-ecommerce/category/Jackets"}
style={{
display: "flex",
flexDirection: "row",
alignItems: "center",
justifyContent: "space-between",
}}
>
<span>Jackets</span>{" "}
<span>
<Jackets className="iconpower" />
</span>
</Link>
<Link
to={"/carvel-ecommerce/category/Womens"}
style={{
display: "flex",
flexDirection: "row",
alignItems: "center",
justifyContent: "space-between",
}}
>
<span>Womens</span>{" "}
<span>
<Womens className="iconpower" />
</span>
</Link>
{/* <Link
to={"/carvel-ecommerce/category/Mens"}
style={{
display: "flex",
flexDirection: "row",
alignItems: "center",
}}
>
<span>Mens</span>{" "}
<span>
<Mens className="iconpower" />
</span>
</Link> */}
</div>
</>
)}
{addToCarrito.length > 0 ? (
<footer id="site-footer">
<div className="container clearfix">
<div className="right">
{" "}
{pickData}
<h1 className="total">
Total: <span>${totalPrice} </span>
</h1>
<Link to={"/checkout"} className="btn">
Checkout
</Link>
<MdOutlineCleaningServices
onClick={() => clear()}
className="cleared"
/>
</div>
</div>
</footer>
) : (
""
)}
</>
);
};
export default Cart;

Scroll to the bottom of a scrollable div in react

I've tried numerous solutions to try scroll to the bottom of a div as at the bottom user feedback can be found on whether their registration form successfully submitted.
var objDiv = document.getElementById("form");
objDiv.scrollTop = objDiv.scrollHeight;
and
window.scrollTo(0,document.body.scrollHeight);
and
window.scrollTo(0,document.querySelector("#form").scrollHeight);
With no success
Here's the react code for the form
return (
<div
className={styles.register_container}
id="register-container"
style={{
height: "100%",
overflow: "scroll",
}}
>
<HomeIcon />
<div className={styles.login_button_container}>
<p>Already have an account? </p>
<button
onClick={() => {
router.push("/login");
}}
>
Log in
</button>
</div>
<div
style={{
padding: "60px 0",
height: "100%",
maxWidth: "300px",
display: "flex",
flexDirection: "column",
alignItems: "center",
}}
id="form"
>
<img
src="/assets/Logo/ROA_logowhite.png"
style={{
height: "100px",
maxWidth: "100px",
}}
onClick={() => {
var objDiv = document.getElementById("form");
objDiv.scrollTop = objDiv.scrollHeight;
}}
/>
{page === 2 && (
<div style={{ width: "100%" }}>
<button className="back-button" onClick={backButtonHandler}>
<FontAwesomeIcon icon={faAngleLeft} />
Back
</button>
</div>
)}
{page === 1 && loginDetails}
{page === 2 && personalDetails}
<div style={{ width: "100%", padding: "5px 0" }}>
<button
className="form-button"
onClick={buttonHandler}
style={{ minHeight: "50px" }}
>
{submitButton}
</button>
</div>
{loading && (
<div
style={{
padding: "5px",
width: "100%",
display: "flex",
justifyContent: "center",
alignItems: "center",
}}
>
<ReactLoading
type="spin"
color="#1dd760"
height={50}
width={50}
id="loader"
/>
</div>
)}
{registrationError && (
<p className="form-submit-error">
Registration error, refresh your page and try again
</p>
)}
{true && (
<div>
<p
style={{ marginBottom: "10px" }}
className="form-submit"
id="submit"
>
Redirecting to login ... You should receive a welcome email, if
not please try registering again or visit the{" "}
<a href="/contact" style={{ color: "#1dd760" }}>
contact
</a>{" "}
page.
</p>
</div>
)}
</div>
</div>
);
I can't directly focus on the submit success message as setState is asynchronous in react. Just need a function that allows me to scroll the bottom of the div when the next/submit button is clicked
The proper way to access/modify DOM elements in React function components is to use the useRef hook.
https://reactjs.org/docs/hooks-reference.html#useref
Here is an example how you can solve your problem:
import * as React from "react";
const Component: React.FunctionComponent = () => {
const ref = React.useRef<HTMLDivElement>(null);
const [success, updateSuccess] = React.useState(false);
const buttonHandler = () => {
updateSuccess(true);
if (ref.current) {
const offsetBottom = ref.current.offsetTop + ref.current.offsetHeight;
window.scrollTo({ top: offsetBottom });
}
};
return (
<div>
...
<button onClick={buttonHandler}>Scroll</button>
{success ? (
<div
ref={ref}
style={{ height: "2000px", display: !success && "none" }}
>
Long Success Message
</div>
) : null}
</div>
);
};
export default Component;

Javascript array slicing based on filter

I'm stuck on writing out logic that will show more comments if user clicks show more comments.
How would i go about performing this logic that filters based on the following: initially there are 2 comments that show(out of 7 total comments). I want to break this down as user keeps clicking on show more. Should show 5 more comments, 3 more comments, 1 more comment, until there is no more comments.
I'm not too sure on what im doing.
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";
const ourStyle = {
backgroundColor: "#FAFAFA",
border: "1px solid #f2f2f2",
borderRadius: "4px",
padding: "15px 20px",
margin: "15px",
};
function CommentList(props: any) {
const [showMore, setShowMore] = useState<Number>(2);
const [openModal, setOpenModal] = useState(false);
const [showLessFlag, setShowLessFlag] = useState<Boolean>(false);
const lastIndexOfComments = props.comments.length - 1;
const startIndex = 0;
console.log(lastIndexOfComments);
const showComments = (e) => {
e.preventDefault();
const subtract = props.comments.length - 2 ;
console.log("testing", subtract);
setShowMore(subtract);
// setShowLessFlag(true);
};
const handleClickOpen = () => {
setOpenModal(true);
};
const handleCloseModal = () => {
setOpenModal(false);
};
.....
const showMoreComments = () => {
return props.comments
.slice(startIndex, 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>
));
};
const ourComments = props.comments;
console.log("before comments", ourComments);
console.log("fsfsfsftestingcomments", ourComments.slice(0, showMore));
return (
<Grid>
<Fragment>
<div style={{ margin: "30px 0px" }}>
<OurSecondaryButton onClick={(e) => showComments(e)} component="span" color="secondary">
View 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(startIndex, 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);
If you have all comments already fetched, you could simply set a limit and only show the comments with an index lower than the limit.
Check this out: https://stackoverflow.com/a/44071932/10955418

Re-render the same component with different parameter

I am working on a react project with similar functionality to a social media site. I have a user profile component below that has links to other user profiles(towards bottom of code below) that are being followed by the current user. Essentially what I am trying to do is re-render the same component with a different user. However, the link to the new user profile doesn't result in the getProfile action getting called so the redux state doesn't update. How can I navigate to the new profile and have the useEffect hook get called again with the new username?
Thank You!
import React, { useEffect, useState } from "react";
import PropTypes from "prop-types";
import { connect } from "react-redux";
import { Link } from "react-router-dom";
import GalleryItem from "../gallery-item/gallery-item.component";
import {
getProfile,
addFollow,
removeFollow
} from "../../redux/profile/profile.actions";
import { FontAwesomeIcon } from "#fortawesome/react-fontawesome";
import { faSpinner, faUserEdit } from "#fortawesome/free-solid-svg-icons";
const Profile = ({
getProfile,
addFollow,
removeFollow,
auth,
profile: { userProfile, loading },
props
}) => {
const userAlias = props.match.params.alias;
useEffect(() => {
getProfile(userAlias);
}, [getProfile]);
return loading ? (
<div class="d-flex justify-content-center">
<FontAwesomeIcon
icon={faSpinner}
className="fa-spin"
style={{ height: "50px", width: "50px", color: "white" }}
/>
</div>
) : (
<div className="container ">
<div className="row">
<div className="col-md-12 align-self-center">
<img
className="rounded-circle float-left shadow-lg"
alt="100x100"
src={userProfile.userProfileImage}
data-holder-rendered="true"
style={{ height: "200px", width: "200px" }}
/>
<div
className="vertical-center"
style={{ marginLeft: "260px", marginTop: "50px" }}
>
<h2>
{auth.user === null || auth.user.alias !== userAlias ? (
<b style={{ color: "white" }}>{userAlias}</b>
) : auth.user.alias === userAlias ? (
<b style={{ color: "white" }}>
{userAlias}
<Link className="" to="/profile/edit">
<FontAwesomeIcon
icon={faUserEdit}
className="fontAwesome"
style={{ paddingLeft: "10px", color: "limegreen" }}
/>
</Link>
</b>
) : (
<b>{userAlias}</b>
)}
</h2>
<p>
<b style={{ color: "white" }}>
{" "}
{userProfile.posts.length} Posts
</b>
<b style={{ color: "white" }}>
{" "}
{userProfile.followers.length} Followers{" "}
</b>
<b style={{ color: "white" }}>
{" "}
{userProfile.following.length} Following{" "}
</b>
</p>
{auth.user === null || auth.user.alias === userAlias ? null : auth
.user.alias !== userAlias &&
userProfile.followers.some(
e => e.userAlias === auth.user.alias
) ? (
<button
type="button"
className="btn btn-primary btn-lg "
onClick={e => removeFollow(userProfile.userId)}
>
Following
</button>
) : auth.user.alias !== userAlias ? (
<button
type="button"
className="btn btn-primary btn-lg "
onClick={e => addFollow(userProfile.userId)}
>
Not Following
</button>
) : (
<button
type="button"
className="btn btn-primary btn-lg "
disabled
>
Follow/Unfollow
</button>
)}
</div>
</div>
</div>
<hr />
<div className="row d-flex justify-content-center">
{userProfile.posts.map((post, i) => (
<GalleryItem key={i} post={post} />
))}
</div>
{userProfile.following.length > 0 ? (
<div>
<h1 className="text-white text-center mt-5">Following</h1>
<hr />
**<div className="row justify-content-center text-center px-auto">
{userProfile.following.map((profile, i) => (
<Link className="" to={`/profile/${profile.userAlias}`}>
<img
className="rounded-circle border border-info m-4"
alt="100x100"
src={profile.getFollowingUserProfileImageUrl}
data-holder-rendered="true"
style={{ height: "80px", width: "80px" }}
/>
<div
className="vertical-center"
style={{ marginBottom: "20px", color: "black" }}
>
<h5>{profile.userAlias}</h5>
</div>
</Link>
))}
</div>**
</div>
) :(<div></div>)}
</div>
);
};
Profile.propTypes = {
getProfile: PropTypes.func.isRequired,
profile: PropTypes.object.isRequired,
auth: PropTypes.object.isRequired,
props: PropTypes.object.isRequired
};
const mapStateToProps = (state, ownProps) => ({
auth: state.auth,
profile: state.profile,
props: ownProps
});
export default connect(
mapStateToProps,
{ getProfile, addFollow, removeFollow }
)(Profile);
You need to track userAlias in the useEffect's dependencies list, the api callback will be called each time it changes.
const userAlias = props.match.params.alias;
useEffect(() => {
getProfile(userAlias);
}, [getProfile, userAlias]);

Edit button + populate field with redux / react

I need send the data line from DataTable to another page and populate the fields with React or Redux... how can i do that?
class Dtable extends Component {
componentWillMount() {
this.props.getList();
}
actionTemplate(rowData, column) {
return <div>
<Button type="button" icon="fa-search" className="ui-button-success"></Button>
<Button type="submit" icon="fa-edit" onClick={console.log(column)} className="ui-button-warning" ></Button>
</div>
}
render() {
return (
<div>
<Form onSubmit={this.props.create} />
<div className="content-section implementation" style={{ paddingTop: 1 + '%' }}>
<DataTable key="idPessoa" value={this.props.list} paginator={true} paginator={true} rows={10} rowsPerPageOptions={[5, 10, 20]} >
<Column field="idPessoa" header="Propriedade" style={{ width: 5 + '%' }} />
<Column field="nome" header="Propriedade" />
<Column field="email" header="Propriedade" />
<Column field="latitude" header="Relatório" style={{ width: 15 + '%' }} />
<Column field="longitude" header="Ativo" style={{ width: 5 + '%' }} />
<Column header="Opções" body={this.actionTemplate} style={{ textAlign: 'center', width: '100px' }} />
</DataTable>
</div>
</div>
)
}
}
const mapStateToProps = state => ({ list: state.upload.list })
const mapDispatchToProps = dispatch => bindActionCreators({ getList, create, showUpdate }, dispatch)
export default connect(mapStateToProps, mapDispatchToProps)(Dtable)
I just add the arrow function on my event ..this solve my problem..thanks guys.
actionTemplate = (rowData, column) => {
return <div>
<Button type="button" icon="fa-search" imediate='true' onClick={() => this.teste(rowData.nome,rowData.email)} className="ui-button-success"></Button>
<Button type="button" icon="fa-edit" imediate='true'
onClick={() => console.log(rowData)} className="ui-button-warning" ></Button>
</div>
}
teste = (nome,mail) => {
console.log(nome)
this.setState({name:nome,email:mail})
}

Categories

Resources