react-pdf - Error: Target container is not a DOM element - javascript

I am using React with react-pdf and trying to render a PDF into my modal. However, my modal gets loaded on a button click, so it's not loaded on app load. But it is trying to call the PDF rendering call on app load and thus generating the error: 'Error: Target container is not a DOM element'. I'm not sure of how to fix this issue.
Here is my entire modal component:
import ReactModal from 'react-modal';
import React, { useEffect, useRef } from 'react';
import ReactDOM from 'react-dom';
import PropTypes from 'prop-types';
import ReactPDF, { PDFViewer } from '#react-pdf/renderer';
import CloseButton from './CloseButton';
import MessageHub from '../message/MessageHub';
import PDFPlacard from '../placards/PDFPlacard';
const PDF = () => (
<PDFViewer>
<PDFPlacard />
</PDFViewer>
);
const PlacardsModal = (props) => {
const { openPlacards, setOpenPlacards, customStyles } = props;
const numPlacards = React.createRef();
const ref = useRef(null);
// this call needs to happen after the modal and #PDFPlacard is rendered
ReactDOM.render(<PDF />, document.getElementById('PDFPlacard'));
const handleSubmit = (evt) => {
evt.preventDefault();
if (numPlacards.current.value === '') {
ref.current('Please fill in the number of placards.');
} else {
// submit form
}
};
return (
<ReactModal
isOpen={openPlacards}
style={customStyles}
className={'print-placards-modal'}
closeTimeoutMS={1000}
>
<CloseButton setOpenModal={setOpenPlacards} />
<h2>Print Placards</h2>
{/* eslint-disable-next-line react/no-children-prop */}
<MessageHub children={(add) => (ref.current = add)} />
<form className={'form'} onSubmit={handleSubmit}>
<div className={'form-group row'}>
<label
htmlFor={'numPlacards'}
className={'col-sm-6 col-form-label'}
>
Number of Placards:
</label>
<div className={'col-sm-6'}>
<input
id={'numPlacards'}
type={'number'}
className={'form-control'}
ref={numPlacards}
/>
</div>
</div>
<button
className={'btn btn-primary d-block mx-auto mb-2'}
type={'submit'}
value={'Print'}
/>
</form>
<div id={'PDFPlacard'} />
</ReactModal>
);
};
PlacardsModal.propTypes = {
openPlacards: PropTypes.bool,
setOpenPlacards: PropTypes.func,
customStyles: PropTypes.object,
title: PropTypes.string
};
export default PlacardsModal;
Here is PDFPlacard.js:
import React from 'react';
import {
Page,
Text,
View,
Document,
StyleSheet
} from '#react-pdf/renderer';
// Create styles
const styles = StyleSheet.create({
page: {
flexDirection: 'row',
backgroundColor: '#E4E4E4'
},
section: {
margin: 10,
padding: 10,
flexGrow: 1
}
});
// Create Document Component
const PDFPlacard = (type) => (
<Document>
<Page size="letter" style={styles.page}>
<View style={styles.section}>
<Text>Section #1</Text>
</View>
<View style={styles.section}>
<Text>Section #2</Text>
</View>
</Page>
</Document>
);
export default PDFPlacard;
And my index.js:
import React from 'react';
import { render } from 'react-dom';
import 'bootstrap/dist/css/bootstrap.min.css';
import 'bootstrap/dist/js/bootstrap.min';
import './index.css';
import App from './App';
const title = 'title';
render(<App title={title} />, document.getElementById('root'));
// eslint-disable-next-line no-undef
module.hot.accept();
The parent is loading the PlacardsModal like this:
...
<button
className={'btn btn-info mb-3'}
onClick={() => setOpenPlacards(true)}
>
Placards
</button>
...
<PlacardsModal
openPlacards={openPlacards}
setOpenPlacards={setOpenPlacards}
customStyles={customStyles}
/>

Finally got the answer from another source. I should not have been making that ReactDOM.render( call at all. I should just have been including the PDF components on my page.
Like this:
...
<button
className={'btn btn-primary d-block mx-auto mb-2'}
type={'submit'}
value={'Print'}
/>
</form>
<!-- not this -->
<div id={'PDFPlacard'} />
<!-- this -->
<PDF />
</ReactModal>
);
};
...

Related

Error props.render - React hook form with react-datapickers

I have problem with React&NextJS and React hook form and react datapickers. I get an error message: Uncaught TypeError: props.render is not a function. I understand that following an update you have to put render prop in the Controller component but I can't manage to set it up with react-datapickers. Has anyone been there before?
PAGE
import React, { useState } from 'react';
import ReactDOM from 'react-dom';
import { useForm, Controller } from 'react-hook-form';
import ReactDatePicker from 'react-datepicker';
//Components
import ButtonsResult from '../components/ButtonsResult';
//Style
import 'react-datepicker/dist/react-datepicker.css';
let renderCount = 0;
export default function DataPickersExample(props) {
const { handleSubmit, control } = useForm({});
const [data, setData] = useState(null);
renderCount++;
return (
<form
onSubmit={handleSubmit((data) => setData(data))}
className='form'
>
<div className='container'>
<section>
<label>React Datepicker</label>
<Controller
as={ReactDatePicker}
control={control}
valueName='selected'
onChange={([selected]) => selected}
name='ReactDatepicker'
className='input'
placeholderText='Select date'
/>
</section>
<ButtonsResult {...{ data }} />
</div>
</form>
);
}
COMPONENTS BUTTON
import React from 'react';
function ButtonsResult({ data}) {
return (
<>
{data && (
<pre style={{ textAlign: 'left', color: 'white' }}>
{JSON.stringify(data, null, 2)}
</pre>
)}
<button className='button'>submit</button>
</>
);
}
export default ButtonsResult;````

How can I show a modal using an animation with Tailwind and react.js?

I am trying when I click on a modal to have an animation to show the modal but I don't achieve to do that using Tailwind and react.
Here is my code :
import React, { useState, useCallback } from "react";
import ReactDOM from "react-dom";
import Wrapper from "./Wrapper";
import Input from "./Input";
import "./styles.css";
import Button from "./Button";
import Modal from "./Modal";
function App() {
const [showModal, setShowModal] = useState(false);
const handleShowModal = useCallback(() => {
setShowModal(!showModal);
}, [showModal]);
const handleCloseModal = useCallback(() => {
setShowModal(false);
}, []);
return (
<div className="p-4">
<h1 className="text-red-500 text-center">PlayGround</h1>
<Wrapper className="p-2">
<Input />
</Wrapper>
<Wrapper className="p-2">
<Button onClick={handleShowModal}>Show Modal</Button>
{showModal && <Modal onCancel={handleCloseModal} />}
</Wrapper>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
And you can see my full code here :
my full project
I would like something like that :
the goal
How can I do that ?
Thank you very much !
I recommend using headless ui
you can use like this
import { Transition } from '#headlessui/react'
import { useState } from 'react'
function MyComponent() {
const [isShowing, setIsShowing] = useState(false)
return (
<>
<button onClick={() => setIsShowing((isShowing) => !isShowing)}>
Toggle
</button>
<Transition
show={isShowing}
enter="transition-opacity duration-75"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="transition-opacity duration-150"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
I will fade in and out
</Transition>
</>
)
}

a problem with the shopping cart button in react

I'm trying to make a button where every time I click it adds the item to the cart, but the problem is that when I click nothing happens, as if it were not even a button:
Product.js :
import React from 'react'
import './Product.css'
import {useStateValue} from './StateProvider'
function Products({id,title,image,price,rating}) {
const [state,dispatch] = useStateValue();
const addToBasket = () => {
dispatch({
type: 'ADD_TO_BASKET',
item:{
id: id,
title: title,
image: image,
price: price,
rating: rating,
},
});
};
return (
<div className="product">
<div className="product_info">
<p>{title}</p>
<p className="product_price">
<small>$</small>
<strong>{price}</strong>
</p>
<div className="product_rating">
{Array(rating).fill().map((_,i) => (
<p>⭐</p>
))}
</div>
</div>
<img src={image} alt="" />
<button onClick={addToBasket}>Add to Basket</button>
</div>
);
}
export default Products;
Reducer.js :
export const initialState ={
basket:[],
};
const reducer =(state,action)=>{
console.log(action);
switch(action.type){
case "ADD_TO_BASKET":
return {
...state,
basket:[...state.basket,action.item],
};
default:
return state;
}
};
export default reducer;
Index.js :
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { StateProvider } from './StateProvider';
import reducer, {initialState} from './reducer'
ReactDOM.render(
<React.StrictMode>
<StateProvider initialState={initialState} reducer={reducer}>
<App />
</StateProvider>
</React.StrictMode>,
document.getElementById('root')
);
reportWebVitals();
Header.js (where I put the basket logo):
import React from 'react';
import './Header.css';
import SearchIcon from '#material-ui/icons/Search'
import ShopppingBasketIcon from '#material-ui/icons/ShoppingBasket'
import {Link} from 'react-router-dom'
import { useStateValue } from "./StateProvider"
function Header() {
const [{basket},dispatch] = useStateValue();
return (
<div className="header">
<Link to="/">
<img className="header__logo" src="http://pngimg.com/uploads/amazon/amazon_PNG11.png"/>
</Link>
<div className="header__search">
<input className="header__searchInput" type="text"/>
<SearchIcon className="header__searchIcon"/>
</div>
<div className="header__nav">
<Link to="/checkout">
<div className="header__optionBasket">
<ShopppingBasketIcon/>
<span className="header__optionLineTwo
header__basketCount">{basket?.lenght}</span>
</div>
</Link>
</div>
</div>
)
}
export default Header
therefore, where I find the problem is that when I click "add to cart" it does not click anything, as if the button did not exist and does not take any action..
try preventing default behaviour like so
const addToBasket = (e) => {
e.preventDefault();
dispatch({
type: 'ADD_TO_BASKET',
item:{
id: id,
title: title,
image: image,
price: price,
rating: rating,
},
});
};
and you can also try setting a type on the button
<button type="button" onClick={addToBasket}>Add to Basket</button>

Why isn't the darkBaseTheme for material-ui applied?

import React from 'react';
import ReactDOM from 'react-dom';
import darkBaseTheme from 'material-ui/styles/baseThemes/darkBaseTheme';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import getMuiTheme from 'material-ui/styles/getMuiTheme';
import {Tabs, Tab} from 'material-ui/Tabs';
const styles = {
headline: {
fontSize: 24,
paddingTop: 16,
marginBottom: 12,
fontWeight: 400,
},
};
const LoginTabs = () => (
<Tabs>
<Tab label="Login" >
<div>
<h2 style = {styles.headline}>Login</h2>
<p>
This is an example tab.
</p>
<p>
You can put any sort of HTML or react component in here. It even keeps the component state!
</p>
</div>
</Tab>
<Tab label="Sign Up" >
<div>
<h2 style = {styles.headline}>Sign Up</h2>
<p>
This is another example tab.
</p>
</div>
</Tab>
</Tabs>
);
class LoginApp extends React.Component {
constructor () {
super();
this.muiTheme = darkBaseTheme;
}
componentWillMount () {
console.log(this.muiTheme);
}
render() {
return(
<div>
{LoginTabs()}
</div>
)
}
}
const Main = () => (
<MuiThemeProvider muiTheme={getMuiTheme(darkBaseTheme)}>
<LoginApp />
</MuiThemeProvider>
);
// ========================================
ReactDOM.render(
<Main />,
document.getElementById('root')
);
The tabs are rendered with the default light theme even though I've specified that darktheme using muiThemeProvider.
Most of this code is copied from the material-ui website and I'm not sure what is wrong. Can anybody suggest a fix?
I think the palette is being overwritten at some point, but I'm not sure where.
You can place the MuiThemeProvider at the root - it is not required on all components.
You can make the theme dark by setting type to dark. While it's only a single property value change, internally it modifies the value of the following keys:
palette.text
palette.divider
palette.background
palette.action
The theme can be set up this way.
import CssBaseline from '#material-ui/core/CssBaseline';
import { MuiThemeProvider, createMuiTheme } from '#material-ui/core/styles';
import { Provider } from 'react-redux';
const theme = createMuiTheme({
palette: {
type: 'dark',
},
});
export default function component(props) {
return (
<MuiThemeProvider theme={theme}>
<div>
<CssBaseline />
<Header />
<AppBody />
</div>
</MuiThemeProvider>
);
}
https://material-ui.com/customization/themes/#type-light-dark-theme-

Material UI cannot pop up dialog with ReactJS

I am learning the material ui and i am testing a few examples of the dialog. What I want is a popup dialog that contains two textfields: login and password, and two buttons: submit and cancel.
with the code below, il compiled but I cannot pop up the dialog when clicking the button "DIALOG". there are 2 errors:
DialogSimple.js
import React from 'react';
import Dialog from 'material-ui/Dialog';
import RaiseButton from 'material-ui/RaisedButton';
import TextFieldLogin from './TextFieldLogin';
import injectTapEventPlugin from 'react-tap-event-plugin';
export default class DialogSimple extends React.Component {
constructor(props) {
super(props);
this.state = {open: true};
injectTapEventPlugin();
}
handleOpen = () => {
this.setState({open: true});
};
handleClose = () => {
this.setState({open: false});
};
render() {
const actions = [
<div>
<TextFieldLogin />
<RaiseButton
label="Annuler"
primary={true}
onTouchTap={this.handleClose}
/>,
<RaiseButton
label="Submit"
primary={true}
keyboardFocused={true}
onTouchTap={this.handleClose}
/>,
</div>
];
return (
<div>
<RaiseButton label="Dialog" onTouchTap={this.handleOpen}/>
<Dialog
title="login"
actions={actions}
modal={false}
open={this.state.open}
onRequestClose={this.handleClose}
>
login
</Dialog>
</div>
);
}
}
TextFieldLogin.js
import React from 'react';
import TextField from 'material-ui/TextField';
const TextFieldLogin = () => (
<div>
<h3>Veuillez login</h3>
<TextField
hintText="Votre login"
floatingLabelText="Login"
/><br />
<TextField
hintText="Votre mot de passe"
type="password"
floatingLabelText="Password"
/><br />
</div>
);
export default TextFieldLogin;
App.js
import React from 'react';
import ReactDOM from 'react-dom';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import DialogSimple from './DialogSimple'
const App = () => (
<MuiThemeProvider>
<div>
<DialogSimple/>
</div>
</MuiThemeProvider>
);
ReactDOM.render(
<App />,
document.getElementById('app')
);
After I clicked the button"DIALOG", it becomes black and creates more errors:
I tried react-tap-event-plugin but it didn't solve the problem.

Categories

Resources