Hiding and showing content on click using React - javascript

In a nutshell, i am creating a case study for a potential job, the employer wants me to use a React app to create it...
I want to create a button that has the start function that:
Hides original content
displays the hidden content,
i got the hidden content to show but the original content is still visible, any help?
my code below:
import React, { useState } from 'react'
function Body() {
const [show, setShow] = useState(true);
const [hide, setHidden] = useState(true);
return (
<>
<div className='container'>
<div className="start-container">
<h2>Click Start To View The Application</h2>
<button onClick={ () => setShow(s => ! s) } className='btn'>Start!</button>
</div>
{/* URL Link Input */}
<div>
{!show ? <form action="GET">
<input type="text" />
<button className='btn'>Submit</button>
</form> : null }
</div>
</div>
</>
)
}
export default Body

You are close, you need to have the original content in the ternary so it's hidden once you toggle show. I also changed setShow to set show to false rather than the previous value since it doesn't matter because the button is not toggable because once you click it and can't re toggle the original content.
import React, { useState } from 'react'
function Body() {
const [show, setShow] = useState(true);
return (
<div className='container'>
{show ? (
<div className="start-container">
<h2>Click Start To View The Application</h2>
<button onClick={() => setShow(false)} className='btn'>Start!</button>
</div>
) : (
<form action="GET">
<input type="text" />
<button className='btn'>Submit</button>
</form>
)
</div>
)
}
export default Body

it dose not need hide state and you can toggle visibility just with show state. try this:
{ show ? <form action="GET">
<input type="text" />
<button className='btn'>Submit</button>
</form> : null
}

This should work.
import React, { useState } from 'react';
function Body() {
const [show, setShow] = useState(false);
return (
<>
<div className="container">
{/* URL Link Input */}
<div>
{show ? (
<form action="GET">
<input type="text" />
<button className="btn">Submit</button>
</form>
) : (
<div className="start-container">
<h2>Click Start To View The Application</h2>
<button onClick={() => setShow(!show)} className="btn">
Start!
</button>
</div>
)}
</div>
</div>
</>
);
}
export default Body;

You could use an appStarted state and then render your component conditionnally:
const { useState } = React
function Body() {
const [appStarted, setAppStarted] = useState(false)
return (
<div className="container">
{appStarted ? (
<div>
<h2>Hidden Content</h2>
</div>
) : (
<div className="start-container">
<h2>Click Start To View The Application</h2>
<button onClick={ () => setAppStarted(true) } className='btn'>Start!</button>
</div>
)}
</div>
)
}
ReactDOM.render(<Body />, document.getElementById("root"))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="root"></div>

Related

How to create "Selected tab" in Next.Js?

I am trying to create selected tab in Next.Js.
The User will have the option to search for data it can be Users or Posts, what the user will search for will be selected by clicking on one of the buttons.
Once the user clicks on the button the button will change background to blue.
However I can't make it to work properly, when the User clicks on the button the .Selected class gets added to the button but the button doesn't render the CSS.
import React, { MouseEventHandler, ReactElement, useState } from 'react'
import { PageWithLayout } from '../components/Layouts/LayoutConfig'
import MainLayout from '../components/Layouts/MainLayout'
import style from '../styles/Search.module.css'
const Search: PageWithLayout = () => {
const [searchPosts, setPostsSearch] = useState < String > ();
const setSearchOption = (searchFor: String) => {
let searchOption = '';
if (searchFor == 'POSTS') {
searchOption = 'POSTS';
} else {
searchOption = 'USERS';
let button = document.getElementById('usersOption') as HTMLElement;
button.className += style.Selected;
}
console.log(searchOption);
setPostsSearch(searchOption);
}
return (
<>
<div className='pageContent'>
<div className={style.SearchBarContainer}>
<div className={style.SearchContainer}>
<i className="fa-solid fa-magnifying-glass"></i>
<input className={style.SearchBar} type={'text'} placeholder='Search...' />
</div>
<div className={style.SearchOptions}>
<button id='usersOption' onClick={() => setSearchOption('USERS')}>Users</button>
<button id='postsOption' onClick={() => setSearchOption('POSTS')}>Posts</button>
</div>
</div>
<div className='SearchedContent'>
</div>
</div>
</>
)
}
Search.getLayout = function getLayout(page: ReactElement) {
return (
<MainLayout>
{page}
</MainLayout>
)
}
export default Search
you can use searchOption data for className style
import React, { MouseEventHandler, ReactElement, useState } from 'react'
import { PageWithLayout } from '../components/Layouts/LayoutConfig'
import MainLayout from '../components/Layouts/MainLayout'
import style from '../styles/Search.module.css'
const Search: PageWithLayout = () => {
const [searchPosts, setPostsSearch] = useState<String>();
return (
<>
<div className='pageContent'>
<div className={style.SearchBarContainer}>
<div className={style.SearchContainer}>
<i className="fa-solid fa-magnifying-glass"></i>
<input className={style.SearchBar} type={'text'} placeholder='Search...'/>
</div>
<div className={style.SearchOptions}>
<button id='usersOption' className={searchPosts === 'USERS' ? style.Selected : undefined } onClick={() => setPostsSearch('USERS')}>Users</button>
<button id='postsOption' className={searchPosts === 'POSTS' ? style.Selected : undefined } onClick={() => setPostsSearch('POSTS')}>Posts</button>
</div>
</div>
<div className='SearchedContent'>
</div>
</div>
</>
)
}
Search.getLayout = function getLayout(page: ReactElement){
return(
<MainLayout>
{page}
</MainLayout>
)
}
export default Search
Just have a state for active searchOption and apply the class conditionally directly into the JSX.
const [activeSearchOption, setActiveSearchOption] = useState('USERS')
return (
<>
<div className='pageContent'>
<div className={style.SearchBarContainer}>
<div className={style.SearchContainer}>
<i className="fa-solid fa-magnifying-glass"></i>
<input className={style.SearchBar} type={'text'} placeholder='Search...'/>
</div>
<div className={style.SearchOptions}>
<button id='usersOption' className={activeSearchOption === 'USERS' ? 'active' : ''} onClick={() => setSearchOption('USERS')}>Users</button>
<button id='postsOption' className={activeSearchOption === 'POSTS' ? 'active' : ''} onClick={() => setSearchOption('POSTS')}>Posts</button>
</div>
</div>
<div className='SearchedContent'>
</div>
</div>
</>
)

How to change props object name when it's clicked in react?

I'm creating a youtube clone using react js and i used this icon
import HomeIconfilled from '#mui/icons-material/Home';
import HomeIcon from '#mui/icons-material/HomeOutlined';
That looks like this HomeIconfilled
which gets rendered by calling this function
<Sidebariconfunc Icon={HomeIconfilled} Title="Home"/>
That takes 2 parameters and reder the icon
function Sidebariconfunc({Icon,Title}) {
return (
<div className='SidebarRow'>
<div className='Sidebar_Icon'>
<Icon/>
</div>
<div className='Slidebar_Title'>
{Title}
</div>
</div>
)
}
How can i chane the props name to HomeIcon when i click on the icon so that it changes to this this icon HomeIcon
Thamks !
function SidebarIcon({ActiveIcon, InactiveIcon, title, isActive}) {
return (
<div className='SidebarRow'>
<div className='Sidebar_Icon'>
{isActive ? <ActiveIcon/> : <InactiveIcon />
</div>
<div className='Slidebar_Title'>{Title}</div>
</div>
)
}
Usage:
const [isActive, setIsActive] = React.useState(false)
return (
<a onClick={() => setIsActive(!isActive)>
<SidebarIcon
ActiveIcon={HomeIconfilled}
InactiveIcon={HomeIcon}
title='Home'
isActive={isActive}
/>
</a>
)

I keep getting .map() is not a function upon first load, but it works when refreshed...any ideas why? MERN stack

So, I have this appointments array coming in from its parent component. This component should map over the array, and then return a div for each item that occurs at a date later than today. Then, when the user clicks the "confirm" button it should re-render the list and remove that item that was just clicked from the list of rendered divs.
The problem is when it re-renders, I get the same "appointments.map() is not a function" error. If I click refresh the component renders as expected with the div that was clicked on removed from the list.
I can't seem to figure out why, as this component shouldn't even load unless the appointments array has a length (as it states in the parent component).
This is the parent component:
import React, { useEffect } from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { Link } from 'react-router-dom'
import { getAppointments } from '../../../actions/appointment'
import ConfirmAppointment from '../Appointments/ConfirmAppointment'
const Dashboard = ({user}) => {
const dispatch = useDispatch()
useEffect(() => {
//get appointment data
dispatch(getAppointments(user?.result._id))
}, [dispatch])
const appointments = useSelector((state)=>state?.usersReducer?.appointment)
return (
<>
<div>
<h3>Welcome {user?.result?.firstName}! :D</h3>
{/* <Link to='/bookappointment'>
<button className="ui button" style={{backgroundColor: '#adad85'}}>Book an appointment</button>
</Link> */}
<Link to="/healthhistory/update" >
<button className="ui button" style={{backgroundColor: '#adad85'}}>Update Health History</button>
</Link>
<Link to="/dashboard/receipts">
<button className="ui button" style={{backgroundColor: '#adad85'}}>View Appointment Receipts</button>
</Link>
{appointments?.length === 0 ? (
<div>Loading ...</div>
) : (
<ConfirmAppointment user={user} appointments={appointments} />
)
}
</div>
</>
)
}
export default Dashboard
And this is the component with the .map function:
import React, { useState } from 'react'
import { useDispatch } from 'react-redux'
import { confirmAppointment } from '../../../actions/appointment'
const ConfirmAppointment = ({user, appointments}) => {
const dispatch = useDispatch()
const { _id } = user?.result
const today = new Date()
const [reasonForMassage, setReasonForMassage] = useState('')
const [treatmentConsent, setTreatmentConsent] = useState(false)
const [glutes, setGlutes] = useState(false)
const [chest, setChest] = useState(false)
const [abdomen, setAbdomen] = useState(false)
const [innerThighs, setInnerThighs] = useState(false)
const [areasToAvoid, setAreasToAvoid] = useState('')
const formData = {
reasonForMassage,
consents: {
treatmentConsent,
glutes,
chest,
abdomen,
innerThighs,
areasToAvoid
}
}
const handleSubmit = (e, appointmentId) => {
e.preventDefault()
setTreatmentConsent(true)
//update appointment with the appointment id
dispatch(confirmAppointment(_id, appointmentId, formData))
clear()
}
const clear = () => {
setReasonForMassage('')
setGlutes(false)
setChest(false)
setAbdomen(false)
setInnerThighs(false)
setAreasToAvoid(false)
}
return (
appointments?.length === 0 ? (
<div>
No upcoming appointments
</div>
) : (
<div style={{marginTop: '3em'}}>
<h4>Upcoming Appointments</h4>
{appointments && appointments?.map((appointment) => (
new Date(appointment?.date) >= today && appointment?.consents?.treatmentConsent !== true ? (
<div style={{marginBottom: '3em'}} key={appointment._id} >
<table className="ui table">
<thead>
<tr>
<th>Date</th>
<th>Time</th>
<th>Duration</th>
</tr>
</thead>
<tbody>
<tr>
<td>{appointment?.date}</td>
<td>{appointment?.time}</td>
<td>{appointment?.duration}</td>
</tr>
</tbody>
</table>
<form className="ui form" onSubmit={(e)=>handleSubmit(e, appointment?._id)} >
<div className="ui fields">
<div className="ui field">
<label>Reason for booking massage:</label>
<input type="text" value={reasonForMassage} onChange={(e)=>setReasonForMassage(e.target.value)}/>
</div>
<div className="ui field">
<h5>I give consent to massage the following areas:</h5>
<div>
<input type="checkbox" value={glutes} onChange={(e)=>setGlutes(e.target.checked)} />
<label>Glutes</label>
<input type="checkbox" value={abdomen} onChange={(e)=>setAbdomen(e.target.checked)} />
<label>Abdomen</label>
<input type="checkbox" value={chest} onChange={(e)=>setChest(e.target.checked)} />
<label>Chest</label>
<input type="checkbox" value={innerThighs} onChange={(e)=>setInnerThighs(e.target.checked)} />
<label>Inner thighs</label>
</div>
</div>
<div className="ui field">
<label>Are there any other areas you would not like to be massaged?</label>
<input type="text" value={areasToAvoid} onChange={(e)=>setAreasToAvoid(e.target.value)} />
</div>
</div>
<button type="submit" className="ui button">Confirm Appointment</button>
</form>
</div>
) : (
<div></div>
)
))}
</div>
)
)
}
export default ConfirmAppointment

How can I stop the React buttons from rendering synchronously?

Every time I click the "increase" or "decrease" buttons for a certain player, I want the score to increase for that player only. However, right now when I click either of the buttons it increases both scores. I know it is probably something simple that I am completely overlooking, but any help is appreciated. Thank you in advance!
Here is my code https://codesandbox.io/s/objective-curran-6ogn3?file=/src/App.js:0-2090:
import "./styles.css";
import {Component, useState} from 'react';
export default function App() {
const [count, setCount] = useState(0);
const [playerScore, setplayerScore] = useState([{
nameOne: 'Player 1'
}, {
nameTwo: 'Player 2'
}
]);
const increase = () => {
setCount(count + 1);
setplayerScore(playerScore);
};
const decrease = () => {
setCount(count - 1);
setplayerScore(playerScore);
};
return (
<main>
{/* player 1*/}
<div>
{playerScore.map((player) => {
return (
<div>
<h2 className="name">{player.nameOne}</h2>
</div>
);
})}
</div>
<div>
<div className="score">{count}</div>
{/* increase button */}
<button onClick={increase}>
Increase
</button>
{/* decrease button */}
<button onClick={decrease}>
Decrease
</button>
</div>
{/* player 2 */}
<div>
{playerScore.map((player) => {
return (
<div>
<h2 className="name">{player.nameTwo}</h2>
</div>
);
})}
</div>
<div>
<div className="score">{count}</div>
<section>
<button onClick={increase}>Increase</button>
<button onClick={decrease}>Decrease</button>
</section>
</div>
</main>
);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
I did this fork based on your code. https://codesandbox.io/s/cranky-hooks-q9ntu?file=/src/App.js
I have refactored some logic and added the functionality that I understand you want. Specially the increase/decrease logic.
The main error was that you were using same state for the entire array, so the value will always be the same for all the items.

How to make a component (popup modal) appear only once using React hooks or otherwise (React/Next js)

I want to make a popup modal appear only once per visit (I don't want it to appear every time someone goes back to the index page). Is there a way to do this using hooks or is there a better method?
export default function Popup() {
const [visible, setVisible] = React.useState(true);
if(!visible) return null;
return (
<div className={styles.popup} onClick={() => setVisible(false)}>
{/* <div className={styles.popupInner}> */}
<div className={styles.popupInner}>
<div className={styles.buttonContainer}><Button color="danger" className={styles.button}>Okay</Button></div>
</div>
{/* </div> */}
</div>
)
}
You could do with localstorage and useEffect hook
why localstorage ?
You could achieve same result using useContext hook. But at the time of refresh.Hooks not hold the previous value.so better use localstorage to store the pop status
export default function Popup() {
const [visible, setVisible] = React.useState(false);
useEffect(()=>{
let pop_status = localStorage.getItem('pop_status');
if(!pop_status){
setVisible(true);
localStorage.setItem('pop_status',1);
}
},[])
if(!visible) return null;
return (
<div className={styles.popup} onClick={() => setVisible(false)}>
{/* <div className={styles.popupInner}> */}
<div className={styles.popupInner}>
<div className={styles.buttonContainer}><Button color="danger" className={styles.button}>Okay</Button></div>
</div>
{/* </div> */}
</div>
)
}
export default function Popup() {
const [visible, setVisible] = React.useState(true);
if(!visible) return null;
return (
<div className={styles.popup}>
<button onClick={() => setVisible(false)}>Click</button>
{ visible ? <div className={styles.popupInner}>
<div className={styles.popupInner}>
<div className={styles.buttonContainer}>
<Button color="danger" className={styles.button}>Okay</Button>
</div>
</div>
</div> : "" }
</div>
)
}

Categories

Resources