reactjs Modal not being called - reactjs

Hi everyone I am new to react but have the task to implement this modal. Unfortunately If I click on the button nothing happens. I could not find a solution and to my total confusion it seems like there are many different ways to implement this kind of modals.
Does anyone have a suggestion please?
The modal itself:
import React, { useState } from 'react'
import './BookingUpdate.css';
function Modal({ setOpenModal, children } : {setOpenModal:any, children:any}) {
if(!setOpenModal) return null;
return (
<div className="modalBackground">
<div className="modalContainer">
<div className="titleCloseBtn">
<button
onClick={() => {
setOpenModal(false);
}}
>
X
</button>
</div>
<div className="title">
<h1>Are You Sure You Want to Continue?</h1>
</div>
<div className="body">
<p>The next page looks amazing. Hope you want to go there!</p>
</div>
<div className="footer">
<button
onClick={() => {
setOpenModal(false);
}}
id="cancelBtn"
>
Cancel
</button>
<button>Continue</button>
</div>
</div>
</div>
);
}
export default Modal;
The file from which it is called:
import React, { useState } from 'react';
import FullLayout from '../components/FullLayout';
import Loading from '../components/Loading';
import { Booking, Formatting } from 'flexspace-commons';
import { Table, Form, Col, Row, Button } from 'react-bootstrap';
import { Search as IconSearch, Download as IconDownload, X as IconX , Settings as IconSettings } from 'react-feather';
import ExcellentExport from 'excellentexport';
import { withTranslation } from 'react-i18next';
import { TFunction } from 'i18next';
import type * as CSS from 'csstype';
import Modal from "../components/BookingUpdate";
interface State {
loading: boolean
start: string
end: string
modalIsOpen: boolean
}
interface Props {
t: TFunction
}
class Bookings extends React.Component<Props, State> {
data: Booking[];
constructor(props: any) {
super(props);
this.data = [];
let end = new Date();
let start = new Date();
start.setDate(end.getDate() - 7);
this.state = {
loading: true,
start: Formatting.getISO8601(start),
end: Formatting.getISO8601(end),
modalIsOpen: false
};
this.toggleBookingModal = this.toggleBookingModal.bind( this );
}
.
.
.
toggleBookingModal = (booking: Booking) => {
this.setState( { modalIsOpen: ! this.state.modalIsOpen } );
<Modal setOpenModal={this.state.modalIsOpen} >
</Modal>
}
renderItem = (booking: Booking) => {
const btnStyle: CSS.Properties = {
['padding' as any]: '0.1rem 0.3rem',
['font-size' as any]: '0.875rem',
['border-radius' as any]: '0.2rem',
};
return (
<tr key={booking.id}>
<td>{booking.user.email}</td>
<td>{booking.space.location.name}</td>
<td>{booking.space.name}</td>
<td>{Formatting.getFormatterShort().format(booking.enter)}</td>
<td>{Formatting.getFormatterShort().format(booking.leave)}</td>
<td><Button variant="info" style={btnStyle} onClick={() => this.toggleBookingModal(booking)}><IconSettings className="feather" /></Button></td>
<td><Button variant="danger" style={btnStyle} onClick={() => this.cancelBooking(booking)}><IconX className="feather" /></Button></td>
</tr>
);
}
.
.
.

Related

Solved|React-Boostrap - <Collapse> defaulting to open when the child is a function

I was testing the collapse tag in a function in a separate test app and it was working, but when I attempted to implement it in this class it keeps defaulting to open.
I added a test function open() & it shows <Collapse> should be closed. Double clicking the first menu item to open/close doesn't do anything to <Collapse>, but does toggle this.state.isOpen.
When the function this.listPages() is removed & replaced with <div> test </div> it works properly.
import './index.css';
import 'bootstrap/dist/css/bootstrap.css';
import React from 'react';
import { Component } from 'react';
import ReactDOM from 'react-dom/client';
import { Collapse } from 'react-bootstrap';
class Menu extends Component {
constructor(props) {
super(props);
this.state = {
pages: ['a', 'b', 'c'],
selectedPage: 'a',
isOpen: false,
};
}
toggle() {
this.setState({isOpen: !this.state.isOpen})
}
selectPage(page) {
this.setState({ selectedPage: {page}})
}
listPages() {
let p;
p = this.state.pages.filter( page => page !== this.state.selectedPage);
return(
p.map((page, index) => {
console.log(page)
return (
<div
className={page + ' menu-item'}
onClick={() => {this.selectPage(page); this.toggle();}}
key={index + 1}
>
{page}
</div>
)
})
);
}
open(boo) {
if(boo === true) {
return(
<div className='menu-item'>open</div>
)
} else {
return(
<div className='menu-item'>closed</div>
)
}
}
render() {
return(
<div className='menu'>
<div
className={ this.state.selectedPage + ' menu-item'}
onClick={() => { this.toggle()} }
key={1}
>
{this.state.selectedPage}
</div>
<Collapse isOpen={this.state.isOpen}>
<>
{this.listPages()}
{this.open(this.state.isOpen)}
</>
</Collapse>
</div>
)
}
}
Solution
wrap it before you tap it
<div>
<>
{this.listPages()}
</>
</div>

How to redirect to another page in react confirmAlert?

I am developing a react shopping cart app. If the user click on 'Clear Cart' button, the entire cart will be cleared. Before that the application should confirm the action and therefore, I used 'React Confirm Alert'. If the user click on 'Yes' button, it will clear the cart and it should navigate to the root page('/'). I searched over the internet and on the StackOverflow and tried the three ways given here. But nothing worked. For both this.props.history.push('/') and this.props.router.push('/') gives me a TypeError saying undefined object and for useHistory() it says violating react hooks principles. Is there anything I can do to make this work? Thanks in advance!
Code :-
import React, { useEffect, useState, Component} from 'react';
import Titles from "../Titles";
import CartColumns from './CartColumns';
import EmptyCart from "./EmptyCart";
import CartList from "./CartList";
import {connect} from "react-redux";
import {Link, Redirect} from "react-router-dom";
import Axios from "axios";
import { confirmAlert } from 'react-confirm-alert'; // Import
import 'react-confirm-alert/src/react-confirm-alert.css' // Import css
const mapStateToProps = ({ session, history}) => ({
session, history
});
class Cart extends Component {
constructor() {
super();
this.removeItem = this.removeItem.bind(this);
}
state = {
Cart: [],
total : 0,
discount: 0
};
componentDidMount() {
if(this.props.session.userId !== null){
this.getItems();
}
}
getItems = () => {
//function to get the items
};
removeItem = (productId) => {
//method to remove an item
};
clearCart = () => {
confirmAlert({
title: 'Clear Cart',
message: 'Are you sure to clear the Cart?',
buttons: [
{
label: 'Yes',
onClick: () => {Axios.get('http://localhost:8000/api/cart/clearCart', {params:{userId: this.props.session.userId}});
} //I want to redirect from here
},
{
label: 'No'
}
]
})
};
checkout= () => {
//Checkout function
};
render() {
let total = this.state.total;
let discount = this.state.discount;
if(this.props.session.username !== null){
return (
<section>
{(this.state.Cart.length > 0) ? (
<React.Fragment>
<Titles name ="Your " title = "Cart">Cart</Titles>
<CartColumns/>
<CartList cart = {this.state.Cart} removeItem={this.removeItem}/>
<div className="container">
<div className="row">
<div className="col-10 mt-2 ml-sm-5 ml-md-auto col-sm-8 text-capitalize text-right">
<h5>
<span className="text-title">Sub Total: </span>
<strong>$ {total}</strong>
</h5>
<h5>
<span className="text-title">Discount: </span>
<strong>$ {discount}</strong>
</h5>
<h5>
<span className="text-title">Total: </span>
<strong>$ {total - discount}</strong>
</h5>
<div className="col-10 mt-2 ml-sm-5 ml-md-auto col-sm-8 text-capitalize text-right">
<button className="btn btn-outline-danger text-uppercase mb-3 px-5" type="button" onClick={this.clearCart}>Clear Cart</button>
<button className="btn btn-outline-info ml-3 text-uppercase mb-3 px-5" type="button" onClick={this.checkout}>Check Out</button>
</div>
</div>
</div>
</div>
</React.Fragment>
) : (
<EmptyCart/>
)
}
</section>
);
} else {
return(
<Redirect to="/login" />
);
}
}
}
export default connect(
mapStateToProps
)(Cart);
I think you have 2 options.
First: Just use window.location method like this
// Simulate a mouse click:
window.location.href = "http://www.example.com";
// Simulate an HTTP redirect:
window.location.replace("http://www.example.com");
Second: Use react state
import React from 'react'
import { Redirect } from 'react-router-dom'
class Cart extends Component {
constructor() {
super();
}
state = {
isRedirect: false
};
const onClick = () =>{
this.setState({isRedirect: true})
}
render() {
let isRedirect = this.state.isRedirect;
if(isRedirect == true){
return <Redirect to='/target' />
}
return (
<div>
...
</div>
)
)
}
window.location.replace("http://localhost:3000/");
This statement will solve your problem. Happy Coding!

React TypeScript Modal

Modal.tsx
import React from 'react';
import './Modal.css'
interface IProps {
show?: boolean;
handleClose?: any;
children: any;
};
const Modal:React.SFC<IProps> = ({ handleClose, show, children }: IProps) => {
const showHideClassName = show ? "display-block" : "display-none";
return <div className={showHideClassName}>
<section className="modal-main">
{children}
<button onClick={handleClose}>close</button>
</section>
</div>;
};
export default Modal;
infoPresenter.tsx
import { Icon } from 'antd';
import React from 'react';
import Modal from '../Modal';
import './Info.css';
class Info extends React.Component{
public state = {
show: false
};
public showModal = () => {
this.setState({ show:true })
}
public hideModal = () => {
this.setState({ show:false })
}
public render(){
return (
<section className="Info">
<div className="InfoTitle">
<h1>Philociphy</h1>
<p>
lorem ipsum
</p>
</div>
<div className="WholeBox">
<div className="BoxLeft" onClick={this.showModal}>
<Modal show={this.state.show} handleClose={this.hideModal}>
<p>Modal</p>
<p>Data</p>
</Modal>
<p>VISION</p>
<Icon type="arrow-left" />
</div>
<div className="BoxRight">
<p>VALUE</p>
<Icon type="arrow-right" />
</div>
</div>
</section>
)
}
}
export default Info;
I want to make the modal. it works but not vanish.
I checked all my state and props, but couldn't find problems.
I don't know where's wrong in my code.
please find it and fix it.
if you have more good idea which make the modal, please let me know how make it in typescript react.
Thanks for all guys who watch this questions

Changes are not reflected in UI in react

When a user like a post, then the count is incremented in ui. Bu when a user remove the like then count ui is not changing though it is changed in server.How to solve it?
When a user like a post, then the count is incremented in ui. Bu when a user remove the like then count ui is not changing though it is changed in server.How to solve it?
import React from 'react';
import moment from 'moment';
import CommentForm from './CommentForm';
import CommentList from './CommentList';
import CommentModal from './CommentModal';
import { connect } from 'react-redux';
import { startAddComment, startAddLike, startRemoveLike } from
'../actions/post';
import { Link } from 'react-router-dom';
import UserInfo from './UserInfo';
class PostListItem extends React.Component{
constructor(props){
super(props);
this.state = {
isliked: false,
commentM: undefined,
likes: this.props.likes
}
}
componentDidMount(){
if(this.props.likes.includes(this.props.user.uid)){
this.setState(() => ({isliked:true}));
}
}
onClickedLike = () =>{
if(this.state.isliked === false){
this.props.dispatch(startAddLike(this.props._id));
this.setState(()=>{
console.log(this.props);
return{
isliked:true
}
});
} else{
this.props.dispatch(startRemoveLike(this.props._id));
this.setState(()=>({isliked:false}));
}
}
openModal = () =>{
this.setState({commentM: this.props.comments});
}
closeModal = () =>{
this.setState(({commentM: undefined}));
}
render(){
return(
<div className="post">
<div className="post__header">
<UserInfo user={this.props.author}
time={this.props.createdAt}/>
{
(this.props.user.uid === this.props.author.uid)?
<Link to={`/edit/${this.props._id}`}
className="post__edit">
Edit</Link>:''
}
{/* <p className="post__time">
{moment(this.props.createdAt).fromNow()}</p> */}
</div>
<div className="post__caption">{this.props.caption}</div>
<img src={this.props.content} className="post__content"/>
<div className="post__extra">
<div className="post__lc">
<button className="post__button"
onClick={this.onClickedLike}
>{this.state.isliked? <i className="fas fa-futbol"></i>
: <i className="far fa-futbol"></i>}
</button>
<button className="post__button"
onClick={this.openModal}><i className="far fa-
comment"></i>
</button>
</div>
{this.props.likes.length !== 0 && <p className="post__like">
{this.props.likes.length} {this.props.likes.length === 1? 'like':'likes'}
</p>} // likes count is not changing while removing the like(ui only)
<CommentModal
commentM={this.state.commentM}
closeModal={this.closeModal}/>
<CommentForm onSubmit={(comment) => {
this.props.dispatch(startAddComment(this.props._id,
comment));
}} />
{this.props.comments && <CommentList comments=
{this.props.comments}/>}
</div>
</div>
);
}
};
const mapStateToProps = (state) => {
return{
user: state.auth
}
}
export default connect(mapStateToProps)(PostListItem);

React - show menu when clicking on just one item from iterating item

I'm having problem with sliding menu in just one item.
When I click on the config button every item shows menu. I tried to figure out something by passing props {mail.id} but I'm afraid I don't understand this.
I would like to have sliding menu just in one item -- the clicked one.
This is ConfigButton
import React, { Component } from "react";
import './Menu.css';
class ConfigButton extends Component {
render() {
return (
<button className="configButton"
onClick={this.props.onClick}
>
<i className="configButtonIcon fas fa-cog"></i>
</button>
);
}
}
export default ConfigButton;
And this is the Component which renders:
import React, { Component } from 'react';
import { NavLink, HashRouter } from 'react-router-dom';
import axios from 'axios';
import Menu from './Menu';
import ConfigButton from './ConfigButton';
const API = myAPI;
const navLinkStyle = {
textDecoration: 'none',
color: '#123e57'
};
class Emails extends Component {
constructor(props) {
super(props);
this.state = {
visible: false,
mails: []
};
this.handleMouseDown = this.handleMouseDown.bind(this);
this.toggleMenu = this.toggleMenu.bind(this);
}
handleMouseDown(e) {
this.toggleMenu();
e.stopPropagation();
}
toggleMenu() {
this.setState({
visible: !this.state.visible
});
}
componentDidMount() {
axios.get(API)
.then(response => {
const mails = response.data;
this.setState({ mails });
})
}
truncate = (text, chars = 140) =>
text.length < chars ? text : (text.slice(0, chars) + '...')
render() {
let mails = this.state.mails;
console.log(mails);
mails = mails.map(mail => {
return (
<div key={mail.id}>
<div className='mail'>
{
!mails.displayed
? <i className="notDisplayed fas fa-circle"></i>
: <i className="displayed far fa-circle"></i>
}
<HashRouter>
<NavLink
to={`/openemail/${mail.id}`}
style={navLinkStyle}
>
<ul className='ulMailWrap'>
<div className='mailHeader'>
<li>{mail.sender}</li>
<li>{mail.created}</li>
</div>
<li>{mail.subject}</li>
<li>{this.truncate(mail.message)}</li>
</ul>
</NavLink>
</HashRouter>
<ConfigButton onClick={this.handleMouseDown} />
<Menu handleMouseDown={this.handleMouseDown}
menuVisibility={this.state.visible}
/>
</div>
</div>
)
});
return (
<div>
{ mails }
</div>
);
}
}
export default Emails;
You can pass a function that will send a different parameter to the handler, depending on value of each element in the array.
Do something like this:
...
<div key={mail.id} onClick={() => this.handleOpenMenu(mail.id)}>
...
Then at the handler:
handleOpenMenu = id => {
// do different stuffs on the id you get here
this.setState({ visibleMenuId: id });
}
And then change the props you are passing to your menu component:
<Menu menuVisibility={this.state.visibleMenuId === mail.id} />

Resources