Я использую reactjs в приложении, и мне нужно добавить страницу регистрации.
Мне нужен родительский макет с общим заголовком и страницей нижнего колонтитула.
Когда кто-нибудь нажмет кнопку «Зарегистрироваться», будут размещены тот же общий заголовок и нижний колонтитул.
-------------------Header.js------------------
import React from 'react';
import { fade,makeStyles } from '@material-ui/core/styles';
import Paper from '@material-ui/core/Paper';
// import Grid from '@material-ui/core/Grid';
import Icon from '@material-ui/core/Icon';
// import { browserHistory, Router, Route } from 'react-router';
import './App.css';
/* AppBar*/
//import { fade, makeStyles } from '@material-ui/core/styles';
import AppBar from '@material-ui/core/AppBar';
import Toolbar from '@material-ui/core/Toolbar';
import IconButton from '@material-ui/core/IconButton';
import Typography from '@material-ui/core/Typography';
import InputBase from '@material-ui/core/InputBase';
import Badge from '@material-ui/core/Badge';
import MenuItem from '@material-ui/core/MenuItem';
import Menu from '@material-ui/core/Menu';
import MenuIcon from '@material-ui/icons/Menu';
import SearchIcon from '@material-ui/icons/Search';
import AccountCircle from '@material-ui/icons/AccountCircle';
import MailIcon from '@material-ui/icons/Mail';
import NotificationsIcon from '@material-ui/icons/Notifications';
import MoreIcon from '@material-ui/icons/MoreVert';
/*App bar */
// import ImgMediaCard from './ImgMediaCard';
// import GridList from '@material-ui/core/GridList';
// import GridListTile from '@material-ui/core/GridListTile';
// import DemoCarousel from './MCarousel';
// var gridListStyle = {
// marginLeft: "40px"
// };
const useStyles = makeStyles(theme => ({
grow: {
flexGrow: 1,
},
menuButton: {
marginRight: theme.spacing(2),
},
title: {
display: 'none',
[theme.breakpoints.up('sm')]: {
display: 'block',
},
},
search: {
position: 'relative',
borderRadius: theme.shape.borderRadius,
backgroundColor: fade(theme.palette.common.white, 0.15),
'&:hover': {
backgroundColor: fade(theme.palette.common.white, 0.25),
},
marginRight: theme.spacing(2),
marginLeft: 0,
width: '100%',
[theme.breakpoints.up('sm')]: {
marginLeft: theme.spacing(3),
width: 'auto',
},
},
searchIcon: {
width: theme.spacing(7),
height: '100%',
position: 'absolute',
pointerEvents: 'none',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
},
inputRoot: {
color: 'inherit',
},
inputInput: {
padding: theme.spacing(1, 1, 1, 7),
transition: theme.transitions.create('width'),
width: '100%',
[theme.breakpoints.up('md')]: {
width: 200,
},
},
sectionDesktop: {
display: 'none',
[theme.breakpoints.up('md')]: {
display: 'flex',
},
},
sectionMobile: {
display: 'flex',
[theme.breakpoints.up('md')]: {
display: 'none',
},
}
}));
/*end App bar work*/
const useGridStyles = makeStyles(theme => ({
root: {
flexGrow: 1,
},
paper: {
// padding: theme.spacing(2),
// textAlign: 'center',
// color: theme.palette.text.secondary,
},
}));
function Header({ history }) {
const Gridclasses = useGridStyles();
const classes = useStyles();
const [anchorEl, setAnchorEl] = React.useState(null);
const [mobileMoreAnchorEl, setMobileMoreAnchorEl] = React.useState(null);
const isMenuOpen = Boolean(anchorEl);
const isMobileMenuOpen = Boolean(mobileMoreAnchorEl);
const handleProfileMenuOpen = event => {
setAnchorEl(event.currentTarget);
};
const handleMobileMenuClose = () => {
setMobileMoreAnchorEl(null);
};
const handleMenuClose = () => {
setAnchorEl(null);
handleMobileMenuClose();
};
const handleMobileMenuOpen = event => {
setMobileMoreAnchorEl(event.currentTarget);
};
const onRegisterClick = () => {
debugger;
history.push('/Register');
};
const menuId = 'primary-search-account-menu';
const renderMenu = (
<Menu
anchorEl={anchorEl}
anchorOrigin={{ vertical: 'top', horizontal: 'right' }}
id={menuId}
keepMounted
transformOrigin={{ vertical: 'top', horizontal: 'right' }}
open={isMenuOpen}
onClose={handleMenuClose}
>
<MenuItem onClick={handleMenuClose}>Profile</MenuItem>
<MenuItem onClick={handleMenuClose}>My account</MenuItem>
</Menu>
);
const mobileMenuId = 'primary-search-account-menu-mobile';
const renderMobileMenu = (
<Menu
anchorEl={mobileMoreAnchorEl}
anchorOrigin={{ vertical: 'top', horizontal: 'right' }}
id={mobileMenuId}
keepMounted
transformOrigin={{ vertical: 'top', horizontal: 'right' }}
open={isMobileMenuOpen}
onClose={handleMobileMenuClose}
>
<MenuItem>
<Icon className="fa fa-plus-circle" />
</MenuItem>
<MenuItem>
<IconButton aria-label="show 4 new mails" color="inherit">
<Badge badgeContent={4} color="secondary">
<MailIcon />
</Badge>
</IconButton>
<p>Messages</p>
</MenuItem>
<MenuItem>
<IconButton aria-label="show 11 new notifications" color="inherit">
<Badge badgeContent={11} color="secondary">
<NotificationsIcon />
</Badge>
</IconButton>
<p>Notifications</p>
</MenuItem>
<MenuItem onClick={handleProfileMenuOpen}>
<IconButton
aria-label="account of current user"
aria-controls="primary-search-account-menu"
aria-haspopup="true"
color="inherit"
>
<AccountCircle />
</IconButton>
<p>Profile</p>
</MenuItem>
</Menu>
);
return (
<Paper className={Gridclasses.paper}>
<div className={classes.grow}>
<AppBar position="static">
<Toolbar>
<IconButton
edge="start"
className={classes.menuButton}
color="inherit"
aria-label="open drawer"
>
<MenuIcon />
</IconButton>
<Typography className={classes.title} variant="h6" noWrap>
Shopping Center
</Typography>
<div className={classes.search}>
<div className={classes.searchIcon}>
<SearchIcon />
</div>
<InputBase
placeholder="Search…"
classes={{
root: classes.inputRoot,
input: classes.inputInput,
}}
inputProps={{ 'aria-label': 'search' }}
/>
</div>
<div className={classes.grow} />
<div className={classes.sectionDesktop}>
<IconButton aria-label="" color="inherit" onClick={onRegisterClick}> Sign Up
</IconButton>
<IconButton aria-label="show 4 new mails" color="inherit">
<Badge badgeContent={4} color="secondary">
<MailIcon />
</Badge>
</IconButton>
<IconButton aria-label="show 17 new notifications" color="inherit">
<Badge badgeContent={17} color="secondary">
<NotificationsIcon />
</Badge>
</IconButton>
<IconButton
edge="end"
aria-label="account of current user"
aria-controls={menuId}
aria-haspopup="true"
onClick={handleProfileMenuOpen}
color="inherit"
>
<AccountCircle />
</IconButton>
</div>
<div className={classes.sectionMobile}>
<IconButton
aria-label="show more"
aria-controls={mobileMenuId}
aria-haspopup="true"
onClick={handleMobileMenuOpen}
color="inherit"
>
<MoreIcon />
</IconButton>
</div>
</Toolbar>
</AppBar>
{renderMobileMenu}
{renderMenu}
</div>
</Paper>
);
}
export default Header;
-------------------Register.js----------------
import React from 'react';
import clsx from 'clsx';
import { makeStyles } from '@material-ui/core/styles';
import IconButton from '@material-ui/core/IconButton';
import Input from '@material-ui/core/Input';
import FilledInput from '@material-ui/core/FilledInput';
import OutlinedInput from '@material-ui/core/OutlinedInput';
import InputLabel from '@material-ui/core/InputLabel';
import InputAdornment from '@material-ui/core/InputAdornment';
import FormHelperText from '@material-ui/core/FormHelperText';
import FormControl from '@material-ui/core/FormControl';
import TextField from '@material-ui/core/TextField';
import Visibility from '@material-ui/icons/Visibility';
import VisibilityOff from '@material-ui/icons/VisibilityOff';
const useStyles = makeStyles(theme => ({
root: {
display: 'flex',
flexWrap: 'wrap',
},
margin: {
margin: theme.spacing(1),
},
withoutLabel: {
marginTop: theme.spacing(3),
},
textField: {
width: 200,
},
}));
function RegisterBuyer() {
const classes = useStyles();
const [values, setValues] = React.useState({
amount: '',
password: '',
weight: '',
weightRange: '',
showPassword: false,
});
const handleChange = prop => event => {
setValues({ ...values, [prop]: event.target.value });
};
const handleClickShowPassword = () => {
setValues({ ...values, showPassword: !values.showPassword });
};
const handleMouseDownPassword = event => {
event.preventDefault();
};
return (
<div className={classes.root}>
<div>
<TextField
label="With normal TextField"
id="standard-start-adornment"
className={clsx(classes.margin, classes.textField)}
InputProps={{
startAdornment: <InputAdornment position="start">Kg</InputAdornment>,
}}
/>
<FormControl className={clsx(classes.margin, classes.withoutLabel, classes.textField)}>
<Input
id="standard-adornment-weight"
value={values.weight}
onChange={handleChange('weight')}
endAdornment={<InputAdornment position="end">Kg</InputAdornment>}
aria-describedby="standard-weight-helper-text"
inputProps={{
'aria-label': 'weight',
}}
/>
<FormHelperText id="standard-weight-helper-text">Weight</FormHelperText>
</FormControl>
<FormControl className={clsx(classes.margin, classes.textField)}>
<InputLabel htmlFor="standard-adornment-password">Password</InputLabel>
<Input
id="standard-adornment-password"
type={values.showPassword ? 'text' : 'password'}
value={values.password}
onChange={handleChange('password')}
endAdornment={
<InputAdornment position="end">
<IconButton
aria-label="toggle password visibility"
onClick={handleClickShowPassword}
onMouseDown={handleMouseDownPassword}
>
{values.showPassword ? <Visibility /> : <VisibilityOff />}
</IconButton>
</InputAdornment>
}
/>
</FormControl>
<FormControl fullWidth className={classes.margin}>
<InputLabel htmlFor="standard-adornment-amount">Amount</InputLabel>
<Input
id="standard-adornment-amount"
value={values.amount}
onChange={handleChange('amount')}
startAdornment={<InputAdornment position="start">$</InputAdornment>}
/>
</FormControl>
</div>
<div>
<TextField
label="With normal TextField"
id="filled-start-adornment"
className={clsx(classes.margin, classes.textField)}
InputProps={{
startAdornment: <InputAdornment position="start">Kg</InputAdornment>,
}}
variant="filled"
/>
<FormControl className={clsx(classes.margin, classes.textField)} variant="filled">
<FilledInput
id="filled-adornment-weight"
value={values.weight}
onChange={handleChange('weight')}
endAdornment={<InputAdornment position="end">Kg</InputAdornment>}
aria-describedby="filled-weight-helper-text"
inputProps={{
'aria-label': 'weight',
}}
/>
<FormHelperText id="filled-weight-helper-text">Weight</FormHelperText>
</FormControl>
<FormControl className={clsx(classes.margin, classes.textField)} variant="filled">
<InputLabel htmlFor="filled-adornment-password">Password</InputLabel>
<FilledInput
id="filled-adornment-password"
type={values.showPassword ? 'text' : 'password'}
value={values.password}
onChange={handleChange('password')}
endAdornment={
<InputAdornment position="end">
<IconButton
aria-label="toggle password visibility"
onClick={handleClickShowPassword}
onMouseDown={handleMouseDownPassword}
edge="end"
>
{values.showPassword ? <Visibility /> : <VisibilityOff />}
</IconButton>
</InputAdornment>
}
/>
</FormControl>
<FormControl fullWidth className={classes.margin} variant="filled">
<InputLabel htmlFor="filled-adornment-amount">Amount</InputLabel>
<FilledInput
id="filled-adornment-amount"
value={values.amount}
onChange={handleChange('amount')}
startAdornment={<InputAdornment position="start">$</InputAdornment>}
/>
</FormControl>
</div>
<div>
<TextField
label="With normal TextField"
id="outlined-start-adornment"
className={clsx(classes.margin, classes.textField)}
InputProps={{
startAdornment: <InputAdornment position="start">Kg</InputAdornment>,
}}
variant="outlined"
/>
<FormControl className={clsx(classes.margin, classes.textField)} variant="outlined">
<OutlinedInput
id="outlined-adornment-weight"
value={values.weight}
onChange={handleChange('weight')}
endAdornment={<InputAdornment position="end">Kg</InputAdornment>}
aria-describedby="outlined-weight-helper-text"
inputProps={{
'aria-label': 'weight',
}}
labelWidth={0}
/>
<FormHelperText id="outlined-weight-helper-text">Weight</FormHelperText>
</FormControl>
<FormControl className={clsx(classes.margin, classes.textField)} variant="outlined">
<InputLabel htmlFor="outlined-adornment-password">Password</InputLabel>
<OutlinedInput
id="outlined-adornment-password"
type={values.showPassword ? 'text' : 'password'}
value={values.password}
onChange={handleChange('password')}
endAdornment={
<InputAdornment position="end">
<IconButton
aria-label="toggle password visibility"
onClick={handleClickShowPassword}
onMouseDown={handleMouseDownPassword}
edge="end"
>
{values.showPassword ? <Visibility /> : <VisibilityOff />}
</IconButton>
</InputAdornment>
}
labelWidth={70}
/>
</FormControl>
<FormControl fullWidth className={classes.margin} variant="outlined">
<InputLabel htmlFor="outlined-adornment-amount">Amount</InputLabel>
<OutlinedInput
id="outlined-adornment-amount"
value={values.amount}
onChange={handleChange('amount')}
startAdornment={<InputAdornment position="start">$</InputAdornment>}
labelWidth={60}
/>
</FormControl>
</div>
</div>
);
}
export default Register
-------------------Index.js-------------------
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter as Router,Switch, Route } from "react-router-dom";
import './index.css';
import Header from './Header.js'
import App from './App';
import * as serviceWorker from './serviceWorker';
import RegisterBuyer from './RegisterBuyer';
ReactDOM.render(
<Router>
<Header />
<Switch>
<Route path="/RegisterBuyer" component={RegisterBuyer} />
<Route exact path="/" component={App} />
</Switch>
</Router>
, document.getElementById('root'));
Я новичок ie с реакцией. Что мне делать в моем коде?
Я взял пример кода для меню и карт отсюда: https://material-ui.com
Application built with
{
"react": "16.13.0",
"react-dom": "^16.13.0",
"react-redux": "^7.2.0",
"redux": "^4.0.4"
"@material-ui/core": "^4.9.5"
}
Проблема, которую я face получает сообщение об ошибке в следующей функции:
const onRegisterClick = () => {
debugger;
history.push('/Register');
};
функция выше отображает ошибку ниже: TypeError: Невозможно прочитать свойство 'pu sh' из неопределенного
HTMLUnknownElement.callCallback node_modules / реагировать -dom / cjs / реагировать-dom.development. js: 188 invokeGuardedCallbackDev node_modules / реагировать-dom / cjs / react-dom.development. js: 237 invokeGuardedCallback node_modules / реагировать-dom / cjs / реагировать-dom.development . js: 292 invokeGuardedCallbackAndCatchFirstError node_modules / реагировать на dom / cjs / реагировать на дом. -dom / cjs / react-dom.development. js: 414 executeDispatchesAndRelease node_modules / реагировать-dom / cjs / реагировать-dom.development. js: 3278 executeDispatchesAndReleaseTopLevel node_modules / реагировать-dom /cjs/react-dom.development.js:3287 forEachAccumulated node_modules / response-dom / cjs / Reaction-dom.development. js: 3259 runEventsInBatch node_modules / реагировать-dom / cjs / реагировать-dom.development. js: 3304 runExtractedPluginEventsInBatch node_modules / реагировать-dom / cjs / реагировать-dom.development. js: 3514 handleTopLevel node_modules / реагировать-dom / cjs / реагировать-dom.development. js: 3558 batchedEventUpdates $ 1 dom / cjs / react-dom.development. js: 21902 batchedEventUpdates node_modules / реагировать-dom / cjs / реагировать-dom.development. js: 1060 dispatchEventForLegacyPluginEventSystem node_modules / реагировать-dom / cjs / реагировать-dom. js: 3568 tryToDispatchEvent node_modules / реагировать-dom / cjs / реагировать-dom.development. js: 4267 dispatchEvent /node_modules/react-dom/cjs/react-dom.development.js:4189 unstable_runWithPriordule node_modules /cjs/scheduler.development.js:653 runWithPriority $ 1 node_modules / реагировать-dom / cjs / реагировать-dom.development. js: 11061 discreteUpdates $ 1 node_modules / реагировать-dom / cj s / react-dom.development. js: 21918 discreteUpdates node_modules / реагировать-dom / cjs / реагировать-dom.development. js: 1071 dispatchDiscreteEvent /node_modules/react-dom/cjs/react-dom.development.js: 4168 Вывод: Компонент SignUp должен отображаться в Layout (Parent) с одинаковыми общими верхним и нижним колонтитулами.
Я пытался следовать инструкциям и искал примеры реализации, но не смог решить / объяснить проблему хорошо.