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.
Related
this is currently the code I have in my App.js file
import './App.css';
import React, { useState } from 'react';
function UserForm(props) {
const cantons = [
{ label: 'Basel', value: 'Basel' },
{ label: 'Zurich', value: 'Zurich' },
{ label: 'Geneve', value: 'Geneve'}
];
const [values, setValues] = useState({
firstName: '',
lastName: '',
canton: 'Basel'
});
const handleChange = e => {
setValues(oldValues => ({
...oldValues,
[e.target.name]: e.target.value
}));
}
function handleSubmit(event) {
event.preventDefault();
//alert('{"firstName": ' + values.firstName + '"lastName" : ' + values.lastName, JSON.stringify(values.canton));
alert(JSON.stringify(values.firstName) +' '+ JSON.stringify(values.lastName) +' '+ JSON.stringify(values.canton));
}
return (
<form onSubmit={handleSubmit}>
<div>
<label htmlFor="firstName">First Name: </label>
<input
id="firstName"
name="firstName"
value={values.firstName}
onChange={handleChange}
/>
</div>
<div>
<label htmlFor="lastName">Last Name: </label>
<input
id="lastName"
name="lastName"
value={values.lastName}
onChange={handleChange}
/>
</div>
<div>
<label>
Canton:
<select
id="canton"
name="canton"
value={values.canton}
onChange={handleChange}
>
{cantons.map((canton) => (
<option value={canton.value}>{canton.label}</option>
))}
</select>
</label>
</div>
<button type="submit">Submit</button>
</form>
);
}
export default UserForm;
how would i be able to create a Component called Page and wrap it around this component and render it. I tried to understand this and apply it to my current code but i keep getting stuck.
this is the normal create-react-app skeleton. i changed the default App()
component to the UserForm component.
my index.js file looks like this:
import React from 'react';
import ReactDOM from 'react-dom/client';
import UserForm from './App';
import reportWebVitals from './reportWebVitals';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<UserForm />
</React.StrictMode>
);
Here I'm providing you the link of sandbox and hopefully it'll help you out to wrap other component into your main component.
https://codesandbox.io/s/restless-shape-bqjut7?file=/src/App.js
Keep Codeing :)
import React from 'react';
const Page = ({ children }) => {
return (
<div>
{children}
</div>
);
};
export default Page;
And now you can wrap it like that:
import React from 'react';
import ReactDOM from 'react-dom/client';
import UserForm from './App';
import Page from './Page';
import reportWebVitals from './reportWebVitals';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<Page>
<UserForm />
<Page>
</React.StrictMode>
);
Is that what you meant?
You can do something like this:
import React from 'react';
import ReactDOM from 'react-dom/client';
import Page from './Page';
import UserForm from './App';
import reportWebVitals from './reportWebVitals';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<Page>
<UserForm />
</Page>
</React.StrictMode>
);
and then in Page.js:
import React from 'react'
const Page = ({ children }) => {
return <div>
<h1>Some Wrapper Page</h1>
{ children }
</div>
}
export default Page
You need to use the children prop: https://reactjs.org/docs/composition-vs-inheritance.html#containment.
You can create a Page component that receives this prop and then render it inside.
function Page({ children }) {
return (
<div>
{children}
</div>
)
}
Instead of using the Page component as <Page />, use <Page> </Page> and everything you put inside it will be placed in the children prop.
root.render(
<React.StrictMode>
<Page>
<UserForm />
</Page>
</React.StrictMode>
);
Above, <UserForm /> is placed in the children prop, which is rendered inside the divs of the Page component.
I am using redux for creating data layer and logic is given below as my code is but the compose button is not working properly it should open a pop up to compose mail. I have imported all the necessary icons and have imported all the buttons, i am using redux form for the data input and firebase for real time database, MailSlice file is very well written but if required, will send it.
Sidebar File
import React from 'react';
import './Sidebar.css';
import {Button, IconButton} from "#mui/material";
import AddIcon from '#mui/icons-material/Add';
import InboxIcon from '#mui/icons-material/Inbox';
import SidebarOption from './SidebarOption';
import StarIcon from '#mui/icons-material/Star';
import AccessTimeIcon from '#mui/icons-material/AccessTime';
import LabelImportantIcon from '#mui/icons-material/LabelImportant';
import NearMeIcon from '#mui/icons-material/NearMe';
import NoteIcon from '#mui/icons-material/Note';
import ExpandMoreIcon from '#mui/icons-material/ExpandMore';
import PersonIcon from '#mui/icons-material/Person';
import DuoIcon from '#mui/icons-material/Duo';
import PhoneIcon from '#mui/icons-material/Phone';
import { useDispatch } from 'react-redux';
import { openSendMessage } from './features/mailSlice';
function Sidebar() {
const dispatch = useDispatch();
return (
<div className="sidebar">
<Button
startIcon={<AddIcon fontSize= "large" />}
className="sidebar__compose"
onClick={() => dispatch(openSendMessage())}
>
Compose
</Button>
<SidebarOption Icon={InboxIcon} title = "Inbox" number={54} selected = {true}/>
<SidebarOption Icon={StarIcon} title = "Starred" number={14} />
<SidebarOption Icon={AccessTimeIcon} title = "Snoozed" number={24} />
<SidebarOption Icon={LabelImportantIcon} title = "Important" number={34} />
<SidebarOption Icon={NearMeIcon} title = "Sent" number={21} />
<SidebarOption Icon={NoteIcon} title = "Drafts" number={4} />
<SidebarOption Icon={ExpandMoreIcon} title = "More" number={39}/>
<div className='sidebar__footer'>
<div className='sidebar__footerIcons'>
<IconButton>
<PersonIcon/>
</IconButton>
<IconButton>
<DuoIcon/>
</IconButton>
<IconButton>
<PhoneIcon/>
</IconButton>
</div>
</div>
</div>
);
}
export default Sidebar;
SendMail File
import { Button } from '#mui/material';
import React from 'react'
import "./SendMail.css";
import CloseIcon from '#mui/icons-material/Close';
import {useForm} from "react-hook-form";
import { useDispatch } from 'react-redux';
import { closeSendMessage } from './features/mailSlice';
import {db} from "./Firebase";
import firebase from "firebase/compat/app";
import "firebase/compat/auth";
import "firebase/compat/firestore";
function SendMail() {
const {register, handleSubmit, watch, errors} = useForm();
const dispatch = useDispatch();
const onSubmit = (formData) => {
console.log(formData);
db.collection("emails").add({
to: formData.to,
subject: formData.subject,
message: formData.message,
timestamp: firebase.firestore.FieldValue.serverTimestamp(),
});
dispatch(closeSendMessage());
};
return (
<div className='sendMail'>
<div className='sendMail__header'>
<h3>New Message</h3>
<CloseIcon onClick={() => dispatch(closeSendMessage())} className='sendMail__close'/>
</div>
<form onSubmit={handleSubmit(onSubmit)}>
<input name='to'
placeholder='To:'
type="email"
ref={register ({required: true})}
/>
{errors.to && (<p className='sendMail__error'>Required field</p>)}
<input name='subject'
placeholder='Subject'
type="text"
ref={register ({required: true})}
/>
{errors.subject && (<p className='sendMail__error'>Required field</p>)}
<input name='message'
placeholder='Message...'
type="text"
className='sendMail__message'
ref={register ({required: true})}
/>
{errors.message && (<p className='sendMail__error'>Required field</p>)}
<div className='sendMail__options'>
<Button className='sendMail__send'
variant='contained'
color='primary'
type='submit'
>
Send
</Button>
</div>
</form>
</div>
)
}
export default SendMail;
I am building an app in which several of the screens have dynamically rendered cards that are mapped to an array of objects called ENTRIES. Each one of these cards can be pressed to navigate to a corresponding screen, however, I cannot seem to get the navigation to work.
I am passing is the screen value from ENTRIES as props from the Settings.js screen into the ClickableCard component, which then gets passed into the TouchableOpacity onClick as this.props.navigation.navigate(screen).
However I keep getting the following error TypeError: undefined is not an object (evaluating '_this3.props.navigation.navigate')
Here is an example of the code below:
App.js File
import React from 'react;
import {createMaterialBottomTabNavigator} from '#react-navigation/material-bottom-tabs';
import {NavigationContainer} from '#react-navigation/native';
import {createStackNavigator} from '#react-navigation/stack';
import Home from './src/screens/Home';
import SettingsScreen from './src/screens/SettingsScreen';
import PrivacyScreen from './src/screens/PrivacyScreen';
import NotificationsScreen from './src/screens/NotificationsScreen';
import SoundsScreen from './src/screens/SoundsScreen';
import ThemeScreen from './src/screens/ThemeScreen';
const PrivacyStack = createStackNavigator();
const SettingsStack = createStackNavigator();
const AuthStack = createStackNavigator();
const MainStack = createStackNavigator();
const Tabs = createMaterialBottomTabNavigator();
const TabNavigator = () => {
return (
<Tabs.Navigator
initialRouteName="Home"
<Tabs.Screen
name="Home"
component={HomeStack}
/>
Tabs.Screen
name="Settings"
component={SettingsStack}
children={this.SettingsStack}
</Tabs.Navigator>
)
}
const AuthStack = () => (
<AuthStack.Navigator>
<AuthStack.Screen
name="Auth"
component={Auth}
/>
</AuthStack.Navigator>
);
const SettingsStackScreen = () => (
<SettingsStack.Navigator>
<SettingsStack.Screen
name="Settings"
component={Settings}
/>
<SettingsStack.Screen
name="Privacy"
component={PrivacyStack}
/>
<SettingsStack.Screen
name="Theme"
component={ThemeScreen}
/>
<SettingsStack.Screen
name="Notifications"
component={NotificationsScreen}
/>
<SettingsStack.Screen
name="Sound"
component={SoundsScreen}
/>
</SettingsStack.Navigator>
);
const PrivacyStack = () => (
<PrivacyStack.Navigator>
<PrivacyStack.Screen
name="Privacy"
component={PrivacyScreen}
/>
<PrivacyStack.Screen
name="Notifications"
component={NotificationsScreen}
/>
</PrivacyStack.Navigator>
);
const App = () => {
return (
<NavigationContainer ref={navigationRef}>
<MainStack.Navigator>
<MainStack.Screen name="Tabs" component={TabNavigator} />
<MainStack.Screen
name="Auth"
component={AuthStack}
options={{gestureEnabled: false}}
/>
</MainStack.Navigator>
</NavigationContainer>
)
}
Settings.js File
import React, {Component} from 'react';
import {TouchableOpacity, ScrollView} from 'react-native;
import ClickableCard from './ClickableCard'
export default class Settings extends Component {
render(screen, index) {
return (
<ScrollView>
{ENTRIES.map((entry, index) => (
<ClickableCard screen={entry.screen} key={entry.index}/>
))}
</ScrollView>
)
}
export default Settings
ClickableCard.js Component
import React, {Component} from 'react';
import {TouchableOpacity, ScrollView} from 'react-native;
export default class ClickableCard extends Component {
constructor(props) {
super(props);
}
render() {
const {
screen,
key
} = this.props
return (
<TouchableOpacity
key={key}
onPress={() => this.props.navigation.navigate(screen)}>
</TouchableOpacity>
)
}
}
entries.js File
import React from 'react';
export const ENTRIES = [
{
name: "Theme",
screen: "ThemeScreen",
},
{
name: "Sounds",
screen: "SoundsScreen",
},
{
name: "Notifications",
screen: "NotificationsScreen",
},
]
You are trying to access navigation outside the navigation stack.
If you are using a functional component you can go with the useNavigation hook but as this is a class based component you will have to send the navigation as a prop or you can do the below as suggested in the documentation
import { useNavigation } from '#react-navigation/native';
class ClickableCard extends Component {
constructor(props) {
super(props);
}
render() {
const { screen, key } = this.props;
return (
<TouchableOpacity
key={key}
onPress={() =>
this.props.navigation.navigate(screen)
}></TouchableOpacity>
);
}
}
const ClickableCardWithNavigation= (props) {
const navigation = useNavigation();
return <ClickableCard {...props} navigation={navigation} />;
}
export default connect(ClickableCardWithNavigation)(TodoList)
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>
);
};
...
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-