我正在仅使用React.js,material-ui和firebase创建一个小型应用程序。我现在不想使用Redux以便对React更加熟悉。 我创建了一个表单,描述如下:
User.jsx:
import React, { Component } from 'react'
import Button from '@material-ui/core/Button'
import Grid from '@material-ui/core/Grid';
import { withStyles } from '@material-ui/core/styles';
import PropTypes from 'prop-types';
import Typography from '@material-ui/core/Typography';
import moment from 'moment';
import db from '../db/config';
import InputTextField from './textField';
import RadioGroup from './radioGroup';
import SnackBar from './snackBar';
const styles = (theme) => ({
button: {
margin: theme.spacing.unit,
},
root: {
display: 'flex',
marginTop: theme.spacing.unit * 8,
padding: theme.spacing.unit * 3,
},
item: {
padding: theme.spacing.unit * 2
}
});
class User extends Component {
state = {
birthday: moment().format('YYYY-MM-DD'),
message: '',
name: '',
open: false,
gender: 'male',
};
handleChange = name => event => {
this.setState({
[name]: event.target.value,
});
};
handleClose = (event, reason) => {
if (reason === 'clickaway') {
return;
}
this.setState({ open: false });
};
handleSubmit = (event) => {
event.preventDefault();
const {
birthday,
name,
gender,
} = this.state;
console.log(`birthday: ${birthday} \n` +
`Name: ${name} \n` +
`gender: ${gender} \n`)
const ref = db.ref('users/');
ref.orderByChild('name').on('child_added', (snapshot) => {
const existedName = (snapshot.val().name).toLowerCase().trim();
const newName = name.toLowerCase().trim();
if(existedName === newName){
this.setState({
open: true,
message: 'Name already exists!!',
})
} else {
ref.push({
name: name.trim(),
gender,
birthday
})
.then(() => {
this.setState({
open: true,
message: 'saved successfully!!',
})
return true;
})
.catch((error) => {
this.setState({
open: true,
message: `Error adding baby: ${error}`,
})
return false;
});
}
})
}
render(){
const { classes } = this.props;
const {
birthday,
message,
name,
open,
gender,
} = this.state;
return (
<div className={classes.root}>
<Grid
container
spacing={40}
justify='center'
direction="column"
alignItems="center"
>
{open && (
<SnackBar
handleClose={this.handleClose}
message={message}
open
/>
)}
<Typography
align="center"
gutterBottom
variant="title"
>
Add New User
</Typography>
<form onSubmit={this.handleSubmit} className={classes.form}>
<Grid item className={classes.item} xs={12}>
<InputTextField
label="Name"
handleChange={this.handleChange('name')}
required
value={name}
type="text"
/>
</Grid>
<Grid item className={classes.item}>
<InputTextField
label="Birthday"
handleChange={this.handleChange('birthday')}
required
value={birthday}
type="date"
InputLabelProps={{shrink: true}}
/>
</Grid>
<Grid item className={classes.item}>
<RadioGroup
name="Gender"
handleChange={this.handleChange('gender')}
value={gender}
/>
</Grid>
<Grid item className={classes.item}>
<Grid
container
direction="row"
>
<Grid item>
<Button
variant="contained"
color="primary"
className={classes.button}
>
Cancel
</Button>
</Grid>
<Grid item>
<Button
variant="contained"
color="primary"
className={classes.button}
type='submit'
>
Save
</Button>
</Grid>
</Grid>
</Grid>
</form>
</Grid>
</div>
)
}
}
User.propTypes = {
classes: PropTypes.object.isRequired,
}
export default withStyles(styles)(User);
SnackBar.jsx:
import React from 'react';
import PropTypes from 'prop-types';
import { withStyles } from '@material-ui/core/styles';
import Button from '@material-ui/core/Button';
import Snackbar from '@material-ui/core/Snackbar';
import IconButton from '@material-ui/core/IconButton';
import CloseIcon from '@material-ui/icons/Close';
const styles = theme => ({
close: {
width: theme.spacing.unit * 4,
height: theme.spacing.unit * 4,
},
});
const SimpleSnackbar = (props) => {
const {
classes,
handleClose,
message,
open,
} = props;
return (
<div>
<Snackbar
anchorOrigin={{
vertical: 'bottom',
horizontal: 'left',
}}
open={open}
autoHideDuration={6000}
onClose={handleClose}
ContentProps={{
'aria-describedby': 'message-id',
}}
message={<span id="message-id">{message}</span>}
action={[
<Button key="undo" color="secondary" size="small" onClick={handleClose}>
UNDO
</Button>,
<IconButton
key="close"
aria-label="Close"
color="inherit"
className={classes.close}
onClick={handleClose}
>
<CloseIcon />
</IconButton>,
]}
/>
</div>
);
}
SimpleSnackbar.propTypes = {
classes: PropTypes.object.isRequired,
handleClose: PropTypes.func.isRequired,
message: PropTypes.string.isRequired,
open: PropTypes.bool.isRequired,
};
export default withStyles(styles)(SimpleSnackbar);
输入表单的其他属性时,在控制台中收到以下警告:Firebase Warning
已添加到Firebase: too much recursion描述的消息too much recursion
我是Firebase的初学者,这是我使用它的第一个应用程序。我认为我错过了一些东西,或者我没有使用合适的功能来获取给定名称是否已经存在。除非将其保存。如果有人试图帮助我解决警告和控制台上显示的错误,我将不胜感激。
答案 0 :(得分:0)
我尝试了此解决方案,并且有效:
handleSubmit = (event) => {
event.preventDefault();
const {
birthday,
name,
gender,
} = this.state;
const ref = db.ref('users/');
const onChildAdded = (snapshot) => {
if(snapshot.exists()){
this.setState({
open: true,
message: 'Name already exists!!',
})
} else {
ref.push({
name: name.trim(),
gender,
birthday
})
.then(() => {
this.setState({
open: true,
message: 'saved successfully!!',
})
return true;
})
.catch((error) => {
this.setState({
open: true,
message: `Error adding baby: ${error}`,
})
return false;
});
}
}
ref.orderByChild('name').equalTo(name).once('value').then(onChildAdded);
}