I'm new to Meteor and I'm studying it. Actually I'm creating a User login, Signup page with a private control panel for each registered user.
I'm able to Signup and Login correctly but I I have two different issues:
- On create user I can not save information to the profile object and it looks like the
onCreateUser
method is not fired at all. - When the user log in I get user information in the Control Panel page, but if I refresh the page I do not receive those information anymore even if the user is still logged in.
Here is the code.
/imports/api/users.js:
import { Meteor } from 'meteor/meteor';
import { Accounts } from 'meteor/accounts-base';
if (Meteor.isServer) {
Meteor.publish('userData', () => {
return Meteor.users.find({ _id: Meteor.userId() }, {
fields: { profile: 1 }
});
});
}
Accounts.onCreateUser((options, user) => {
user.profile = options.profile || {};
user.profile.accountType = options.accountType;
return user;
});
/imports/ui/Signup.js:
import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import { Meteor } from 'meteor/meteor';
import { Accounts } from 'meteor/accounts-base';
import Joi from 'joi';
import validation from 'react-validation-mixin';
import strategy from 'joi-validation-strategy';
import classnames from 'classnames';
import history from '../../utils/history';
class Signup extends Component {
constructor(props) {
super(props);
this.validatorTypes = {
accountType: Joi.string().required().label('Account type'),
email: Joi.string().email().label('Email'),
password: Joi.string().required().min(6).label('Password'),
confirmPassword: Joi.string().required().min(6).valid(Joi.ref('password')).label('Confirm password').options({
language: {
any: {
allowOnly: '!!Passwords do not match'
}
}
})
};
this.getValidatorData = this.getValidatorData.bind(this);
this.renderHelpText = this.renderHelpText.bind(this);
this.getClasses = this.getClasses.bind(this);
this.onSubmit = this.onSubmit.bind(this);
this.state = {
serverError: ''
};
}
componentWillMount() {
if (Meteor.userId()) {
history.replace('/');
}
}
getValidatorData() {
return {
accountType: this.refs.accountType.value,
email: this.refs.email.value,
password: this.refs.password.value,
confirmPassword: this.refs.confirmPassword.value
};
}
renderHelpText(message) {
return (
<span className='validation-error-message'>{message}</span>
);
}
getClasses(field) {
return classnames({
'form-group': true,
'has-error': !this.props.isValid(field)
});
}
onSubmit(e) {
e.preventDefault();
const onValidate = error => {
if (!error) {
let accountType = this.refs.accountType.value;
let email = this.refs.email.value.trim();
let password = this.refs.password.value.trim();
let confirmPassword = this.refs.confirmPassword.value.trim();
Accounts.createUser({ email, password, accountType }, (err) => {
if (err) {
this.setState({
serverError: err.reason
});
} else {
this.setState({
serverError: ''
});
history.replace('/account');
}
});
}
};
this.props.validate(onValidate);
}
render() {
return (
<div className="form-container">
<h3>Create Account</h3>
<form onSubmit={this.onSubmit}>
<div className={this.getClasses('accountType')}>
<select
className="form-control"
name="accountType"
ref="accountType"
placeholder="Account type"
onChange={this.props.handleValidation('accountType')}
>
<option value="">Select account type</option>
<option value="student">Sudent</option>
<option value="teacher">Teacher</option>
<option value="guest">Guest</option>
</select>
{this.renderHelpText(this.props.getValidationMessages('accountType')[0])}
</div>
<div className={this.getClasses('email')}>
<input
className="form-control"
type="text"
name="email"
ref="email"
placeholder="email address"
onChange={this.props.handleValidation('email')}
/>
{this.renderHelpText(this.props.getValidationMessages('email')[0])}
</div>
<div className={this.getClasses('password')}>
<input
className="form-control"
type="password"
name="password"
ref="password"
placeholder="password"
onChange={this.props.handleValidation('password')}
/>
{this.renderHelpText(this.props.getValidationMessages('password')[0])}
</div>
<div className={this.getClasses('confirmPassword')}>
<input
className="form-control"
type="password"
name="confirmPassword"
ref="confirmPassword"
placeholder="confirm password"
onBlur={this.props.handleValidation('confirmPassword')}
/>
{this.renderHelpText(this.props.getValidationMessages('confirmPassword')[0])}
</div>
<button className="btn btn-dark" type="submit">Create</button>
</form>
<div className="meta">
<p>Already have an account? <Link to="/login">Login</Link></p>
</div>
</div>
);
}
};
export default validation(strategy)(Signup);
What I expect is when I create a new use the method in users.js
called Accounts.onCreateUser
get fired and the accountType
information is added to profile. It doesn't happen.
I also expect to always retrieve the current logged in user information in the control panel. Here is the control panel component:
/imports/ui/Account.js:
import React, { Component } from 'react'; import { Meteor } from 'meteor/meteor';
import history from '../../utils/history';
class Account extends Component {
constructor(props) {
super(props);
Meteor.subscribe('userData');
this.state = {
user: {}
}
}
componentWillMount() {
if (!Meteor.userId()) {
history.replace('/login');
}
}
componentDidMount() {
console.log(Meteor.userId()); // I can always get this value
const user = Meteor.users.find({ _id: Meteor.userId() }, {
fields: { profile: 1 }
}).fetch();
console.log(user); // On refresh it is an empty array [].
this.setState({ user });
}
render() {
return (
<div>Hello Account</div>
);
}
};
export default Account;
What I'm doing wrong?