React useEffect and onClick button do not work - reactjs

App.js
import { Container, Row, Col } from "react-bootstrap";
import React, { useState, useEffect } from 'react';
import {person} from "./Data"
import DatesCounts from "./Components/DatesCounts";
import DatesList from "./Components/DatesList";
import DatesAction from "./Components/DatesAction";
function App() {
const [personData, setPersonData] = useState(person)
const onDelet =()=> {
setPersonData([])
}
const onViewData=() => {
setPersonData(person)
}
useEffect(()=>{
setPersonData([])
})
return (
<div className="color-body font">
<Container className="py-5">
<DatesCounts person={person} />
<DatesList person={person} />
<DatesAction deletData={onDelet} viewData={onViewData} />
</Container>
</div>
);
}
export default App;
DatesAction.js
import React from 'react';
import {Row,Col} from 'react-bootstrap';
const DatesAction = ({deletData , viewData}) => {
return (
<Row className=" justify-content-center my-2">
<Col sm="8" className="d-flex justify-content-between">
<button onClick={deletData} className="btn-style p-2">Clear All</button>
<button onClick={viewData} className="btn-style p-2">Show Data</button>
</Col>
</Row>
);
}
export default DatesAction;
I tried to execute useEffect to clear data in the beginning without success.
I also tried to execute onClick buttons Clear All and Show Data without success.
as you see the code is for Dates Reminder the componenets are working but the onClick buttons are not working also the useEffect doesn't work.

you need to send child components personData, instead of person. Since they are receiving the json instead of the useState information
<DatesCounts person={personData} />
<DatesList person={personData} />

To update the state try to use useEffect with dependency on your personData
useEffect(() => {}, [personData])
For setting the initial state, you can use use effect without dependency instead of setting it directly to useState.
useEffect(() => {
setPersonData(person);
}, [])

You don't need a hook especially when dealing with onclick events.
simply have a function which will reset the state and pass it as a prop to child component.
const initialState = { }; //definte initial state.
const [person, setPersons] = useState(initialState);
const resetState = () => {
setPersonState(initialState);
}
//render
<Child onReset={resetState} />

You are missing the dependency array in useEffect but anyway lets improve the performance of your code using React.memo and React.useCallback.
Wrap your function in a React.useCallback so that their reference will be same on next render and will improve some performance but to effectively use useCallback wrap the child component with React.memo
DatesAction.jsx
import React from "react";
import { Row, Col } from "react-bootstrap";
const DatesAction = React.memo(({ deletData, viewData }) => {
return (
<Row className=" justify-content-center my-2">
<Col sm="8" className="d-flex justify-content-between">
<button onClick={deletData} className="btn-style p-2">
Clear All
</button>
<button onClick={viewData} className="btn-style p-2">
Show Data
</button>
</Col>
</Row>
);
});
export default DatesAction;
App.jsx
import { Container, Row, Col } from "react-bootstrap";
import React, { useState, useEffect } from "react";
import { person } from "./Data";
import DatesCounts from "./Components/DatesCounts";
import DatesList from "./Components/DatesList";
import DatesAction from "./Components/DatesAction";
function App() {
const [personData, setPersonData] = useState(person);
const onDelet = React.useCallback(() => {
setPersonData([]);
}, [deps]);
const onViewData = React.useCallback(() => {
setPersonData(person);
}, [deps]);
useEffect(() => {
setPersonData([]);
}, [deps]);
return (
<div className="color-body font">
<Container className="py-5">
<DatesCounts person={person} />
<DatesList person={person} />
<DatesAction deletData={onDelet} viewData={onViewData} />
</Container>
</div>
);
}
export default App;

Related

i can't save data in lcoal storage when i refresh the page

Where is the problem, I can't save data in local storage when i refresh the page and it saved when i clicked but the problem it disappear i used usestate data to keep hook i don't know why i tried all solutions and nothing worked i think the problem released because i use redux and that didn't work well or something else or useeffect didn't work for some reason
import { Button, Col, Container, Row } from "react-bootstrap";
import { useDispatch, useSelector } from "react-redux";
import "./Watchstemp.css"
import { FaEye, FaWindowClose } from "react-icons/fa";
import { addTowatched } from "../rtk/reducers/Watchedslice";
import { clearMovie } from "../rtk/reducers/watchSlice";
import { useEffect, useState } from "react";
function Watchstemp(){
const dispatch = useDispatch()
const posts = useSelector(poster => poster)
const [posters, setPosters] = useState(posts.postSlice)
useEffect(() => {
// storing input name
localStorage.setItem("watchlist", JSON.stringify(posters));
}, [posters]); // Update the dependency array with posters
useEffect(() => {
const data = window.localStorage.getItem('watchlist');
setPosters(data ? JSON.parse(data) : posts.postSlice);
}, []);
return(
<>
<Row>
{
posters.map((post => {
return (
<Col lg={3} md={4} sm={6} key={post}>
<div className="movie-cards">
<div className="overlay">
<img className="img-fluid rounded" src={post} alt={post} />
<div className="inner-card-controls">
<FaEye className="ctrl-btn" onClick={() => dispatch(addTowatched(post))} />
<FaWindowClose className="ctrl-btn" onClick={() => dispatch(clearMovie(post))}/>
</div>
</div>
</div>
</Col>
)
}))
}
</Row>
</>
)
}
export default Watchstemp

ReactJS global state toggle

I am new to reactJS and stuck in an issue. i have a button in header that needs to toggle a class 'show' in a menu which is in some other file. I tried to use global state but do not know how to do that. here is what i did;
LAYOUT FILE
import React, { useState } from "react";
// importing header / menu etc.
function LayoutHome({ children }) {
const [state, setState] = React.useState({ MsgMenu: 'messages-dropdown' });
const handleOpenMsgMenu = (e) => {
e?.preventDefault();
setState({MsgMenu:'messages-dropdown show'});
};
return (
<>
<Header handleOpenMsgMenu={handleOpenMsgMenu} />
<MessageMenu handleOpenMsgMenu={state.MsgMenu} />
{children}
<Footer />
</>
);
}
HEADER
import React, { useState } from "react";
function Header({handleOpenMsgMenu}) {
<button type="button" onClick={handleOpenMsgMenu} className="header-notification-btn">MENU</button >
}
MENU
import React, { useState } from "react";
function MessageMenu({handleOpenMsgMenu}) {
<div id="messages-dropdown" className={handleOpenMsgMenu}>
// CONTENT
</div>
}
To achieve this you can use useState hook to toggle the display of the Menu.
create a new toggle state in global and pass it onto the menu component.
below is the complete code.
import React from "react";
export default function App({children}) {
const [state, setState] = React.useState({ MsgMenu: 'messages-dropdown' });
const [toggle, setToggle] = React.useState(false);
const handleOpenMsgMenu = (e) => {
e?.preventDefault();
setToggle(!toggle);
};
return (
<>
<Header handleOpenMsgMenu={handleOpenMsgMenu} />
<MessageMenu handleOpenMsgMenu={state.MsgMenu} toggle={toggle} />
{children}
</>
);
}
// Header
import React from "react";
function Header({handleOpenMsgMenu}) {
return <button type="button" onClick={handleOpenMsgMenu} className="header-notification-btn">MENU</button >
}
// Menu
import React from "react";
function MessageMenu({handleOpenMsgMenu, toggle}) {
return <div id="messages-dropdown" style={{display: toggle?"block":"none"}}>
<ul>
<li>
{handleOpenMsgMenu}
</li>
</ul>
</div>
}
You can toggle state with !value and then change your class depending on that value
setMenu(() => {
return {
...menu,
show: !menu.show // toggle
};
});
I've made a sample here
For the global state, check out Context or Redux

Passing down Props to "Single Page Views" through components

Hey still new to React but I'm grinding my way through it slowly by building my own personal app/platform. I have a quick question of passing down props to single page views. This is my overview page that will pull in all the teams from my database as such:
import React, { useState, useEffect } from 'react';
import firebase from '../../firebase/firebase.utils'
import Button from '../../Components/GeneralComponents/Button.component'
import * as GoIcons from 'react-icons/go';
import TeamList from '../../Components/Teams/TeamList.Component'
function TeamsPage() {
const [teams, setTeams] = useState([]);
const [loading, setLoading] = useState(false);
const ref = firebase.firestore().collection("teams");
function getTeams() {
setLoading(true);
ref.onSnapshot((querySnapshot) => {
const items = [];
querySnapshot.forEach((doc) => {
items.push(doc.data());
});
setTeams(items);
setLoading(false);
console.log(items);
});
}
useEffect(() => {
getTeams();
},[])
if(loading) {
return <h1>Loading...</h1>
}
return (
<div className="content-container">
<h2>Team Page</h2>
<div className="add-section">
<div className="actions">
<Button
className="bd-btn outlined add-team"
><GoIcons.GoGear/>
Add Team
</Button>
</div>
</div>
<TeamList teams={teams} />
</div>
)
}
export default TeamsPage;
This gets passed into my TeamList Component:
import React from 'react';
import { Link } from 'react-router-dom'
import { TeamCard } from './TeamCard.Component';
const TeamList = props => {
return(
<div className='teams-overview'>
{props.teams.map(team => (
<Link to={`/teams/${team.id}`}>
<TeamCard key={team.id} team={team}/>
</Link>
))}
</div>
)
}
export default TeamList;
Which maps through and then list the Team as a card component with a link that is supposed to route to their id and pass through their data.
Now in my single page view of a team I'm struggling to gain access to that prop data:
import React from 'react'
function TeamSinglePage(team) {
return (
<div className="content-container">
<h1>Single Page View</h1>
<p>Welcome, {team.teamName}</p>
</div>
)
}
export default TeamSinglePage;

How can I use useState to conditionally render?

I am trying to use useState to conditionally render a div but for the life of me I can not figure out how to do it. I think I am close but I can not see what I am doing wrong, I have entirely misunderstood how to do this. What am I doing wrong? I have written this and it does not work..
import React, { useState } from 'react'
import { FontAwesomeIcon } from '#fortawesome/react-fontawesome'
import { faWindowClose } from '#fortawesome/free-solid-svg-icons'
function ElementMenuHeader() {
const [elementMenuOpenClose, setElementMenuOpenClose] = useState(true)
const handleClick = () => setElementMenuOpenClose(false)
return (
<div id="App-Close-Element-Menu-Container"
style={{ display: elementMenuOpenClose ? 'block' : 'none'}}
>
<button id="App-Close-Element-Menu"
onClick={() => handleClick }
>
<FontAwesomeIcon icon={faWindowClose} />
</button>
</div>
);
}
export default ElementMenuHeader
Ideally I would like to be able to set the state of elementMenuOpenClose from other components too, but I will cross this bridge first I think.
You can just use a ternary operator and check a against the state in the operator condition return the div you would like based on the state:
{(elementMenuOpenClose? <div>some tags A </div>: <div>Some tags B </div>)}
You may have a parent component of ElementMenuHeader.
Let's say that is ParentElementMenuHeader.
Inside ParentElementMenuHeader component, you can define like
const ParentElementMenuHeader = () => {
const [elementMenuOpenClose, setElementMenuOpenClose] = useState(true);
...
return (
...
{elementMenuOpenClose && (
<ElementMenuHeader
setElementMenuOpenClose={setElementMenuOpenClose}
...
/>
)}
...
);
}
Inside ElementMenuHeader component,
import React, { useState } from 'react'
import { FontAwesomeIcon } from '#fortawesome/react-fontawesome'
import { faWindowClose } from '#fortawesome/free-solid-svg-icons'
function ElementMenuHeader({setElementMenuOpenClose}) {
const handleClick = () => setElementMenuOpenClose(false)
return (
<div id="App-Close-Element-Menu-Container">
<button id="App-Close-Element-Menu" onClick={handleClick}>
<FontAwesomeIcon icon={faWindowClose} />
</button>
</div>
);
}
export default ElementMenuHeader

Why is this infinite loop happening in the following code? React & useState

I'm going to give you 2 versions of a component i wrote. Why does the FIRST one give me an infinite loop, while the second one works fine?
I isolated the problem but i am wondering why the logic doesn't follow 'under the hood'. No doubt some black magic from useState
//THROWS INFINTE LOOP ERROR
import React, { useState } from 'react';
import PropTypes from 'prop-types';
import { Popover, PopoverHeader, PopoverBody } from 'reactstrap';
import { FontAwesomeIcon } from '#fortawesome/react-fontawesome';
import { faInfoCircle } from '#fortawesome/pro-light-svg-icons';
const HelpIcon = (props) => {
HelpIcon.propTypes = {
title: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
id: PropTypes.string.isRequired,
children: PropTypes.node.isRequired
};
const [isOpen, toggleIsOpen] = useState(false);
return (
<React.Fragment>
<span
className="pointer text-body"
id={props.id}
>
<FontAwesomeIcon icon={faInfoCircle} />
</span>
<Popover
trigger="legacy"
placement="left"
isOpen={isOpen}
target={props.id}
toggle={toggleIsOpen(!isOpen)}{//<-----look here!!!!!!!!!!!!!!!}
>
{props.title !== false && (
<PopoverHeader className="text-body bg-light">
{props.title}
</PopoverHeader>
)}
<PopoverBody className="text-xs cart__rebate_description text-body bg-white">
{props.children}
</PopoverBody>
</Popover>
</React.Fragment>
);
};
export default HelpIcon;
...AND...
//THIS ONE WORKS
//NOTICE THE EXTRA FUNCTION THAT CALLS USESTATE, INSTEAD OF CALLING IT DIRECTLY
import React, { useState } from 'react';
import PropTypes from 'prop-types';
import { Popover, PopoverHeader, PopoverBody } from 'reactstrap';
import { FontAwesomeIcon } from '#fortawesome/react-fontawesome';
import { faInfoCircle } from '#fortawesome/pro-light-svg-icons';
const HelpIcon = (props) => {
HelpIcon.propTypes = {
title: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
id: PropTypes.string.isRequired,
children: PropTypes.node.isRequired
};
const [isOpen, toggleIsOpen] = useState(false);
const toggle = () => toggleIsOpen(!isOpen);
return (
<React.Fragment>
<span
className="pointer text-body"
id={props.id}
>
<FontAwesomeIcon icon={faInfoCircle} />
</span>
<Popover
trigger="legacy"
placement="left"
isOpen={isOpen}
target={props.id}
toggle={toggle}
>
{props.title !== false && (
<PopoverHeader className="text-body bg-light">
{props.title}
</PopoverHeader>
)}
<PopoverBody className="text-xs cart__rebate_description text-body bg-white">
{props.children}
</PopoverBody>
</Popover>
</React.Fragment>
);
};
export default HelpIcon;
this is wrong, and it causes you the loop:
toggle={toggleIsOpen(!isOpen)} // you call the function in a loop
It should be:
toggle={() => toggleIsOpen(!isOpen)}
If you really want to use it your way you must do a double arrow function like this:
const toggle = isOpen => () => {
toggleIsOpen(isOpen)
}
// and use it like
toggle={toggle(!isOpen)}
You are instantly calling toggleIsOpen in the first example. You should always wrap it with another function if you want to call it with arguments other than toggle prop provides.
it is causing infinite since changing state cause re-render in react; if your function call don't cause re-render it will work( kinda, not causing infinite loop) something like this
foo = () => console.log(9)
toggle={foo()}
but since set state will cause re-render your app stuck; here is the call-stack (kinda)
render is called;
it will reach the set-state
state changes
calling render again
it will reach the set-state
state changes
calling render again
and ....

Resources