Show a Modal on react functional component using redux toolkit - javascript

I have a dashboard page that shows a table list of all the posts, for each post I have and an edit button.
I'm trying to pop a modal when the edit button is clicked.
So I created a Modal component, which is rendered by the Dashboard component (this is a high order component equal to the App compo)
and I added a modal slice with redux toolkit and I successfully managed to change the modal state when the edit button is clicked but the modal doesn't show up.
I hope that I was thorough enough with what I'm trying to achieve, I also hope that you will help me guys, and now I'll share with you some of the code.
EditPostModal.jsx
import React from 'react'
import { useSelector, useDispatch } from 'react-redux'
import { makeStyles } from '#material-ui/core/styles'
import Modal from '#material-ui/core/Modal'
import editPostSlice, {
getPostToEditModal,
} from '../../store/slices/editPost'
const useStyles = makeStyles((theme) => ({.....}))
export default function SimpleModal() {
const classes = useStyles()
const modal = useSelector(getPostToEditModal)
const dispatch = useDispatch()
console.log('HEYYYY', modal) // modal is undefined
const handleClose = () => {
dispatch(editPostSlice.actions.closeModal())
}
if (!modal) return null
return (
<Modal
className={classes.modal}
open
onClose={handleClose}
aria-labelledby="simple-modal-title"
aria-describedby="simple-modal-description"
>
<h1>I AM THE MODAL</h1>
</Modal>
)
}

The first step to debug is to check if the modal will open without redux toolkit slice.
Also, can you confirm that the modal variable always return something other than a falsy value?

Related

onHover event on material ui component is not rendering icon

I am currently trying to render a delete icon on an Material UI component, to be more specific, the MenuItem component. I have created a state field in the component's state and set it to false(this.state.isHovering). The idea is that when I hover over the account item, I want to render the delete icon, and when I hover off, it is supposed to go away. I impleneted these event listeners using onMouseEnter and onMouseLeave and attached them over to the MenuItem. I then made it so that the icon only shows when this.state.isHovering is true. However, when I hover over the MenuItem, it does not render. However, if I just implemented the icon without having the state get involved, it renders. I also console logged in the event handlers to make sure that the event is being registered and it does console log both when hovering in and out. Please see my code. Thanks!
handleMouseEnter = () => {
this.setState({
isHovering: true,
})
}
handleMouseLeave = () => {
this.setState({
isHovering: true,
})
}
I think there are a few issues with your code:
the state is never defined
you don't properly update the state
You don't properly conditionally check/use the state
Lots of bugs in the code you provided (looks like an incomplete copy paste)
You can use reactHooks to help define your state and setState functions
This is my best answer, but the code you provided is missing the account variable and a lot of the referenced functions, so it is incomplete. But it should help with your state issues
import React, { Component, Fragment, useState } from 'react';
import { Typography, withStyles } from '#material-ui/core';
import PropTypes from 'prop-types';
import Paper from '#material-ui/core/Paper';
import Grid from '#material-ui/core/Grid';
import Table from '#material-ui/core/Table';
import TableBody from '#material-ui/core/TableBody';
import TableCell from '#material-ui/core/TableCell';
import MenuItem from '#material-ui/core/MenuItem';
import Icon from '#material-ui/core/Icon';
import AccountTypeIcon from './AccountTypeIcon';
class PortDashSideBar extends Component {
const [isHovering, setIsHovering] = useState(false);
handleMouseEnter = () => {
setIsHovering(true);
}
handleMouseLeave = () => {
setIsHovering(false);
}
return <MenuItem
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
className={account.id === currentAccountId ? classes.selectedAccount : classes.unselectedAccount}
hover
name={account.name}
key={account.id}
onClick={ () => this.setCurrentAccount(account.id) }>
<TableCell className={classes.cellAccountIcon}>
<AccountTypeIcon type={this.getAccountById(account.id).type} />
</TableCell>
<TableCell className={classes.cellName}>
<Typography className={classes.accountName}>
{account.label}
</Typography>
<Typography>
<span>
{this.getHoldingsForAccount(account.id)}
</span>
{
isHovering ? <Icon>delete</Icon> : null
}
</Typography>
</TableCell>
</MenuItem>;
}

Delete images if the user is leaving the component React

I have form with a drag and drop component where I can upload images, after this I send these pictures with axios to my backend and save it on server side and then re-render it in a preview mode. My problem is, that if a user uploads some pictures and after that he switches to another page without submitting the form the added pictures are staying on my server side for no reason.
So the question: I want to check inside my component if a user is leaving, show a prompt and if he clicks on the OK button I want to delete all the added pictures from my backend before leaving. How can I detect this?
My simplified snippet:
function MyComp(props) {
const [Images,setImages] = useState([]) // in this array I store the recieved image's URL
const [isBlocking,setIsBlocking] = useState(true) // used for prompt
const handleSubmit = (event) => {
event.preventDefault();
setIsBlocking(false)
}
return(
<Grid container className={classes.mainGrid} direction="row" spacing={2}>
<Grid item xs={4} xl={4}>
<Prompt when={isBlocking} message="There are unsaved datas. Are you sure you want to leave?"/>
<form className={classes.form} onSubmit={handleSubmit}>
... somecode
</Grid>
</Grid>
)
}
export default MyComp
Thanks in advance
Inside React Function Component you can call the prompt when the user is trying to leave , i.e when the component is unmounting
In Class Component of React you can use React componentWillUnmount() and in Function Component You can use useEffect cleanup function
Code for Function Component
import React, { useEffect } from "react";
import { Link } from "react-router-dom";
export default function Home(props) {
useEffect(() => {
return function cleanup() {
alert("unmounting");
//call api and execute your code here
};
}, []);
return (
<div>
<Link to="/home">
On Click I will unmount this component and go to /home
</Link>
</div>
</Link>
);
}
Code for Class Component
import React, { Component } from 'react';
import { Link } from 'react-router-dom';
export default class Test extends Component {
componentWillUnmount() {
alert('unmounting component');
//call your code here
}
render() {
return (
<div>
<Link to='/home'>
On Click I will unmount this component and go to /home
</Link>
</div>
);
}
}
You can check this codesandbox if you want any ref
When you leave the page, the component method componentWillUnmount() fires. I don't recall how this behaves if you were to simply close the browser window as opposed to just navigating away, nor do I recall how you can escape it and stay on the component, but that should at least be a good starting point for you. Obviously you'd have to do a class extending React.Component for this one instead of a straight function.

How to make a "global" component render content based on url route?

I have a FAQ button that's fixed onto the bottom right corner of the screen (it's on every screen of the website), when clicked a modal pops out displaying frequent asked questions and their respective answers, I'd like the modal to display different content based on the url that the user is on.
For example: if the user is on www.example.com/signup then the modal would render the content specific to the sign up process, and when the user is on www.example.com/shop only the faq's related to shopping should appear. This should be taking into account the first part of the url params, so if a user goes to www.example.com/shop/294594 (or any other route that stars with /shop) then the modal still displays the same content as for www.example.com/shop.
Is there any good way to to this with react-router (or any other alternative)? I did some research into react-router useParams hook but I'm not sure if it's the go-to solution since I'm just a beginner in routing. Thanks for your time!
You can create a FAQ component like this https://codesandbox.io/s/react-router-tgh8c?file=/components/FAQ.js
import React from "react";
import { useLocation } from "react-router-dom";
const SignupFaq = () => <p>Sign up questions</p>;
const ShopFaq = () => <p>Shop questions</p>;
const faqs = {
signup: {
component: <SignupFaq />
},
shop: {
component: <ShopFaq />
}
};
function FAQ() {
const { pathname } = useLocation();
const { component } = faqs[pathname.split("/")[1]];
const [modal, showModal] = React.useState(false);
return (
<React.Fragment>
<button onClick={() => showModal(!modal)}>FAQ</button>
<div className="modal">{modal && <div>{component}</div>}</div>
</React.Fragment>
);
}
export default FAQ;

Gatsby open modal window on button click

I'm working on a website about donation using Gatsby v2 (Reactjs) and I need an example like open modal window on button donation click using Gatsby or ReactJS. I search on internet and I got nothing.
Thanks in advance.
Here's a simple (Gatsby) page that makes use of react-modal as an example. In this example I've replaced the default IndexPage in the Gatsby v2's new starter site that you can generate via the CLI.
import React, { Component } from 'react'
import ReactModal from 'react-modal'
import { Link } from 'gatsby'
import Layout from '../components/layout'
ReactModal.setAppElement('#main')
class IndexPage extends Component {
constructor(props) {
super(props)
this.state = {
isModalOpen: false,
}
}
handleModalOpen = event => {
// console.log('handleModalOpen: ', event);
this.setState({ isModalOpen: true })
}
handleModalClose = event => {
// console.log('handleModalOpen: ', event);
this.setState({ isModalOpen: false })
}
render() {
return (
<Layout>
<div id="main">
<h1>Hi people</h1>
<p>Welcome to your new Gatsby site.</p>
<p>Now go build something great.</p>
<Link to="#" onClick={this.handleModalOpen}>
Donate Now
</Link>
</div>
<ReactModal
isOpen={this.state.isModalOpen}
onRequestClose={this.handleModalClose}
contentLabel="Example Modal In Gatsby"
>
<h2>Donate</h2>
<button onClick={this.handleModalClose}>Close Modal</button>
</ReactModal>
</Layout>
)
}
}
export default IndexPage
That should get you going. Best to read up on how to expand on this example using react-modal here (or use an alternative).
First of all the above example will not work because #main doesn't exist, right now the id for Gatsby app is ___gatsby, so it shoul look like this
ReactModal.setAppElement('#___gatsby')
But it's not good to hope that this id is not going to change in the future. So it's better to implement your own React modal component, here is a good example https://www.digitalocean.com/community/tutorials/react-modal-component

How to only render modal in the initial route of the stacknavigator?

The initial screen of my stacknavigator has a modal that shows up upon the occurrence of a certain event ... problem is when I navigate to other screens the modal still shows up when the event is triggered. I want it only to show up when the initial route is showing up.
Maybe you can check this.props.navigation.state.routeName so that you know if it's initial screen or not.
I got this from this document.
https://reactnavigation.org/docs/navigators/navigation-prop
How about using state?
import React, { useEffect,useState } from "react";
const MainScreen = (props) => {
const [seenReminder, setReminder] = useState(false);
useEffect(()=>{
if (!seenReminder){
props.navigation.navigate('reminder')
setReminder(true)
}
}, [seenReminder]);
return (
<View ></View>
);
};
export default MainScreen;

Categories

Resources