Close modal as soon as another one is pressed - reactjs

I want a modal to close once a different modal is pressed, but I'm not sure on how to do it.
Essentially, if modal1 is pressed, it should show the contents of modal1, but as soon as modal2 is pressed,modal1 should disappear and only modal2 should show it's contents. How do I go about this?
I've tried to set it up with an open and close in the onclick but only had problems.
This is how I've got my code currently set up:
const [openQueueList, setOpenQueueList] = useState(false);
const handleOpenQueue = () => {
setOpenQueueList(true);
};
const [openRoomlist, setOpenRoomlist] = useState(false);
const handleOpenRoom = () => {
setOpenRoomlist(true);
};
const [openRoomQueueList, setOpenRoomQueueList] = useState(false);
const handleOpenRoomQueue = () => {
setOpenRoomQueueList(true);
};
in the return
<div class="modal">
<div >
{openQueueList ?
<TrackTable></TrackTable>
: null}
</div>
</div>
<div class="modal">
<div >
{openRoomlist ?
<LobbyUsers> </LobbyUsers>
: null}
</div>
</div>
<div class="modal">
<div >
{openRoomQueueList ?
<QueueSection></QueueSection>
: null}
</div>
Triggering the buttons
<button onClick={handleOpenRoomQueue}>
<QueueMusicIcon></QueueMusicIcon>
</button>
<button onClick={handleOpenRoom}>
<GroupIcon ></GroupIcon>
</button>
<button onClick={handleOpenQueue}>
<AudiotrackIcon></AudiotrackIcon>
</button>

Instead of using a state for each modal you could give each a key.
State would look like this
const [currentModal, openModal] = useState(null);
Then to open
<button onClick={() => openModal('queueList')}>Queue List</button>
<button onClick={() => openModal('roomList')}>Room List</button>
<button onClick={() => openModal('roomQueueList')}>Room Queue List</button>
Then your modals would look something like:
<div className="modal">
{currentModal === 'queueList' ?
<TrackTable></TrackTable>
: null}
{currentModal === 'roomList' ?
<LobbyUsers> </LobbyUsers>
: null}
{currentModal === 'roomQueueList' ?
<QueueSection></QueueSection>
: null}
</div>

Related

setting two states with onClick

I am trying to disable one of the button, when clicked but it is not working. onClick is changing two states, one for the text and one to disable the button.
const [loading, setLoading] = useState();
const [disable, setDisable] = useState(false);
return (
<div>
<p>Data is {loading ? "Loading" : "not Loading"} </p>
<button
onClick={() => {
setLoading(true);
setDisable(true);
}}
disabled={disable}
>
ON
</button>
<button
onClick={() => {
setLoading(false);
setDisable(false);
}}
disabled={disable}
>
OFF
</button>
</div>
);
you should set the "OFF" button to disabled={!disable}
<button
onClick={() => {
setLoading(false);
setDisable(false);
}}
disabled={!disable}
>
OFF
</button>

onClick load react component in the same place

I have a panel with 3 buttons, i want to make onclick on every button, a different component will appear in the same place. How can this logic be done?
<AddNotification />
<EditNotification />
<DeleteNotification />
const AdminPanel = () => {
return (
<Card className={classes.input}>
<div><h1>Notification Panel</h1></div>
<form>
<div className="form-group">
<Button type="submit">Add Notification</Button>
</div>
<div className="form-group">
<Button type="submit">Edit Notification</Button>
</div>
<div className="form-group">
<Button type="submit">Delete Notification</Button>
</div>
</form>
</Card>
)
}
#MLDC No i don't have another divs, i want to replace the buttons with the crossponding component. For example: onclick on Add, then Add component will appears instead of the buttons.
In that case, create a boolean state for every Panel that you have (I created 3 so that you could open the panels simultaneously),
const [isAddPanelOpen, setIsAddPanelOpen] = useState(false);
const [isEditPanelOpen, setIsEditPanelOpen] = useState(false);
const [isDeletePanelOpen, setIsDeletePanelOpen] = useState(false);
Next, apply this to every button
<Button onClick={setIsAddPanelOpen(prevState=>!prevState)}>Add Notification</Button>
<Button onClick={setIsEditPanelOpen(prevState=>!prevState)}>Edit Notification</Button>
<Button onClick={setIsDeletePanelOpen(prevState=>!prevState)}>Delete Notification</Button>
Lastly, Refactor your html to
<div className="form-group">
{isAddPanelOpen ? <AddNotification/> : <Button type="submit">Add Notification</Button>}
</div>
<div className="form-group">
{isEditPanelOpen ? <EditNotification/> : <Button type="submit">Edit Notification</Button>}
</div>
<div className="form-group">
{isDeletePanelOpen ? <DeleteNotification/> :<Button type="submit">Delete Notification</Button>}
</div>
Try this if you want to display one component at a time and hide the others when you click a button
const AdminPanel = () => {
const [componentToDisplay, setComponentToDisplay] = useState("")
return (
<>
<Card className={classes.input}>
<div><h1>Notification Panel</h1></div>
<form>
<div className="form-group">
{componentToDisplay !== "add ? (
<Button type="submit" onCLick={() => setComponentTodisplay("add")}>Add Notification</Button>)
:(<AddNotification />)}
</div>
<div className="form-group">
{componentToDisplay !== "edit ? (
<Button type="submit" onCLick={() => setComponentTodisplay("edit")}>Edit Notification</Button>)
:(<EditNotification />)}
</div>
<div className="form-group">
{componentToDisplay !== "delete ? (
<Button type="submit" onCLick={() => setComponentTodisplay("delete")}>Delete Notification</Button>)
:(<DeleteNotification />)}
</div>
</form>
</Card>
</>
)
}
Or if you want to be able to replace every buttons, use this logic with one state per button
const AdminPanel = () => {
const [addNotif, setAddNotif] = useState(false)
const [editNotif, setEditNotif] = useState(false)
const [deleteNotif, setDeleteNotif] = useState(false)
return (
<>
<Card className={classes.input}>
<div><h1>Notification Panel</h1></div>
<form>
<div className={`form-group ${editNotif || deleteNotif ? "display: none" : "display: flex"}`}>
{!addNotif ? (
<Button type="submit" onCLick={() => setAddNotif(true)}>Add Notification</Button>)
:(<AddNotification setAddNotif={setAddNotif} />)}
</div>
<div className={`form-group ${addNotif || deleteNotif ? "display: none" : "display: flex"}`}>
{!editNotif ? (
<Button type="submit" onCLick={() => setEditNotif(true)}>Edit Notification</Button>)
:(<EditNotification setEditNotif={setEditNotif} />)}
</div>
<div className={`form-group ${addNotif || editNotif ? "display: none" : "display: flex"}`}>
{!deleteNotif ? (
<Button type="submit" onCLick={() => setDeleteNotif(true)}>Delete Notification</Button>)
:(<DeleteNotification setDeleteNotif={setDeleteNotif} />)}
</div>
</form>
</Card>
</>
)
}
Then in your component
const AddNotification = ({setAddNotif}) => {
...
return (
...
<button onCLick={() => setAddNotif(false)}>back</button>
...
)
}
Same logic for the other components
To achieve this logic you need to manage which component is displayed using a state.
This means:
Attribute an arbitrary id to each component.
Store the id of the active component in a useState hook.
Use conditional rendering to display the component that match the current state.
Update the state to the corresponding Id when clicking on each button.
A small example
const [activePanel, setActivePanel] = React.useState(0)
let currentPanel = <Panel0 />
switch(activePanel){
case 0:
currentPanel = <PanelO />
case 1:
currentPanel = <Panel1 />
// Continue as needed
}
return (
<div>
<CurrentPanel/>
<button onClick={() => setActivePanel (0)}> Panel 0 </button>
<button onClick={() => setActivePanel (1)}> Panel 1 </button>
// And so on
</div>
)
You can further refine this by extracting the switch statement into its own component that takes the activePanel as a prop.

Change button value using URI in React.js

I made a few buttons that gonna change it's value into select or deselect. But I want to use URI I got from API fetch.
Here is my code:
const ButtonComponent = () => {
const [isSelected, setIsSelected] = useState(false)
return (
<div className="button">
<button onClick={() => setIsSelected(!isSelected)}>{isSelected ? "Deselect" : "Select"}</button>
<button onClick={() => setIsSelected(!isSelected)}>{isSelected ? "Deselect" : "Select"}</button>
<button onClick={() => setIsSelected(!isSelected)}>{isSelected ? "Deselect" : "Select"}</button>
</div>
)
}
Where I have to put the URI so that it could be saved in the state?
Note: URI state could be array
I am not entirely sure if this is what you are looking for but just let me know if this is ok.
const ButtonComponent = () => {
const [isSelected, setIsSelected] = useState(false)
const [uri, setUri] = useState(null)
return (
<div className="button">
<button
onClick={() => {
setIsSelected(!isSelected)
setUrl('uri1')
}}>
{isSelected ? "Deselect" : "Select"}
</button>
<button
onClick={() => {
setIsSelected(!isSelected)
setUrl('uri2')
}}>
{isSelected ? "Deselect" : "Select"}
</button>
<button
onClick={() => {
setIsSelected(!isSelected)
setUrl('uri3')
}}>
{isSelected ? "Deselect" : "Select"}
</button>
</div>
)
}
Do you want something like this?

How can I change styles in the onClick event?

I want to show/hide the search bar on the top side of the screen.
I am trying to implement an operation where the search bar is shown when the search button is pressed and hides again when the close button of the search bar is pressed.
const showSearchBar = () => {
document.querySelector("#hearder_search_bar").style = {
top : 0
}
};
const hideSearchBar = () => {
document.querySelector("#hearder_search_bar").style = {
top : -71
}
};
return (
<>
<form id = "hearder_search_bar" action="#" className="header__search">
<input type="text" placeholder="Search"/>
<button
type="button"
class="search"
onClick={...}
>
</button>
<button
type="button"
className="close"
onClick={hideSearchBar}
>
</form>
<div className="header__action--search">
<button
className="header__action-btn"
type="button"
onClick={showSearchBar}>
</button>
</div>
</>
);
css
.header__search {
position: absolute;
left: 0;
top: -71px;
}
use react useState hook and let react handle the manipulation of the DOM.
const [shouldShowSearch, setShouldShowSearch] = useState(false);
const toggleShowSearch = () => setShouldShowSearch(prev => !prev);
const label = shouldShowSearch ? 'hide' : 'show';
const top = shouldShowSearch ? '70px' : '0';
//... code
<>
<form id="hearder_search_bar" action="#" className="header__search" style={{top}}>
// ... code
<button
type="button"
className={label}
onClick={toggleShowSearch}
>
</form>
// .. code
<button onclick={toggleShowSearch}>{label} search</button>
You can use conditionnal className
className={headerIsHidden ? 'header__search__hidden' : 'header__search__shown'

how to call ".hidden.bs.dropdown" event using jquery inside react function component

I have a multi select dropdown. I am trying to call a function on dropdown close with all selected values but selected items are always empty.
const [selectedItems, setSelectedItems] = useState([]);
const dropdownRef = useRef(null);
useEffect(() => {
if(!isDropdownLoading)
$(dropdownRef.current).on("hidden.bs.dropdown", e => {
onDropdownClose(selectedItems);
//This function is getting called on dropdown close but selectedItems is always empty array.
});
}
}, [isDropdownLoading]);
const toggleItem=(event,selectedItem)=>{
//here logic to find selected items and update state
setSelectedItems(ArrayWithSelectedItems);
}
if (isDropdownLoading) {
return <p className="drop-down-onloading">Loading...</p>;
}
return (
<div ref={dropdownRef}>
<button
type="button"
data-toggle="dropdown"
aria-haspopup="true"
aria-expanded="false"
title={titleText}
>
{name}
</button>
<div className="dropdown-menu">
{dropDownList.map(item => {
if (item.isVisible) {
return (
<button
className="dropdown-item"
onClick={e => toggleItem(e, item)}
key={item.id}
id={name}
>
<i
className={`${
item.isChecked
? "check-box"
: "empty-box"
}`}
></i>
{item.name}
</button>
);
}
})}
</div>
</div>
);
Why state is always empty array inside Jquery event. This is a function based react component.

Resources