vacuumlabs/react-custom-validation

[Error] Module parse failed

Closed this issue · 2 comments

Hi,

I have started following the example to implement a validation form using your component. Unfortunately, I could not get it to compile. Initially, I thought it was a ES6 stage issue (I have figured out that I had to add stage-0 as presets in Babel), but it seems to be something else.

This is the error I'm receiving when running the command npm start

Thanks in advance for your help and great contribution.

ERROR in ./~/react-custom-validation/lib/validation.jsx
Module parse failed: 
/webapp/node_modules/react-custom-validation/lib/validation.jsx Line 1: Unexpected token
You may need an appropriate loader to handle this file type.
| export {Validate, and} from './Validate'
| export {IsEmail, IsRequired, HasNumber, HasLength, AreSame} from './Rules'
|
 @ ./client/src/components/auth/Signup.jsx 73:18-67

ERROR in ./~/react-custom-validation/lib/Rules.jsx
Module parse failed: /webapp/node_modules/react-custom-validation/lib/Rules.jsx Line 2: Unexpected token
You may need an appropriate loader to handle this file type.
| //import Promise from 'bluebird'
| import validator from 'validator'
|
| export function valid() {
 @ ./client/src/components/auth/Signup.jsx 75:13-57

webpack.config.js

const webpack = require('webpack');
const path = require('path');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
var BrowserSyncPlugin = require('browser-sync-webpack-plugin');

const dirname = __dirname;
const nodeModulesPath = path.resolve(dirname, './node_modules')

module.exports = {
  devtool: 'inline-source-map',
  entry: [
    // Set up an ES6-ish environment
    'babel-polyfill',

    'webpack-hot-middleware/client',
    path.resolve(dirname, './client/src/client.jsx')
  ],
  output: {
    path: path.resolve(dirname, './dist'),
    filename: 'bundle.js',
    publicPath: '/js'
  },
  resolve: {
    extensions: ["", ".js", ".jsx", '.scss', '.css']
  },
  plugins: [
    //new ExtractTextPlugin('example.css', { allChunks: true }),
    new ExtractTextPlugin('client.css'),
    new webpack.optimize.OccurrenceOrderPlugin(),
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NoErrorsPlugin(),
    new BrowserSyncPlugin(
      // BrowserSync options
      {
        // browse to http://localhost:3000/ during development
        host: 'localhost',
        port: 3000,
        // proxy the Webpack Dev Server endpoint
        // (which should be serving on http://localhost:3100/)
        // through BrowserSync
        proxy: 'http://localhost:3100/'
      },
      // plugin options
      {
        // prevent BrowserSync from reloading the page
        // and let Webpack Dev Server take care of this
        reload: false
      }
    )
  ],
  module: {
    preLoaders: [
      {
        //Eslint loader
        test: /\.(js|jsx)$/,
        loader: 'eslint-loader',
        include: [path.resolve(dirname, "./client/src")],
        exclude: [nodeModulesPath]
      },
    ],
    loaders: [
      {
        test:/\.(js|jsx)$/,
        loader: 'babel-loader',
        include: [
          path.resolve(dirname, "./client")
        ],
        query: {
          presets: ['es2015', 'stage-0', 'react', 'react-hmre']
        }
      },
      {test: /\.scss$/,  loader:ExtractTextPlugin.extract('css!sass')},
      {
        //test: /(\.scss|\.css)$/,
        test: /\.css$/, // Only .css files
        loader: 'style!css' // Run both loaders
      }
    ]
  }
};

signup.jsx

import React, { Component, PropTypes } from 'react'
import { defineMessages, FormattedMessage } from 'react-intl'
import Promise from 'bluebird'
import TextField from 'material-ui/lib/text-field';
import FlatButton from 'material-ui/lib/flat-button'
import RaisedButton from 'material-ui/lib/raised-button';
import Card from 'material-ui/lib/card/card'
import CardActions from 'material-ui/lib/card/card-actions'
import CardHeader from 'material-ui/lib/card/card-header'
import CardMedia from 'material-ui/lib/card/card-media'
import CardTitle from 'material-ui/lib/card/card-title'
import CardText from 'material-ui/lib/card/card-text'
import Checkbox from 'material-ui/lib/checkbox'
// Validation packages
import {
  Validate,
  IsEmail,
  IsRequired,
  HasNumber,
  HasLength,
  AreSame} from 'react-custom-validation/lib/validation'
import {valid, invalid} from 'react-custom-validation/lib/Rules'


const IsUnique = ({value, time}) => {
  let isValid = value.indexOf('used') === -1
  let response = isValid ? valid() : invalid('The value is not unique.')
  return Promise.delay(time).then(() => response)
}

const messages = defineMessages({
  passwordText: {
    id: 'global.password',
    description: 'Password text',
    defaultMessage: 'password'
  },
  signupButton: {
    id: 'auth.signupButton',
    description: 'Signup button.',
    defaultMessage: 'Signup'
  },
  usernameText: {
    id: 'global.username',
    description: 'Username text',
    defaultMessage: 'username'
  }
});

let state = {
  userId: 0,
  username: null,
  password: null,
  email: null,
  loggedIn: false,
  resultMessage: ''
};

const styles = {
  general: {
    maxWidth: '400px'
  },
  logo: {
    marginBottom: '30px',
    height: '70px'
  },
  box: {
    fontWeight: '400',
    fontFamily: 'Roboto',
    textAlign: 'left'
  },
  title: {
    textTransform: 'capitalize',
    color: 'white',
    fontWeight: '400',
    fontSize: '2.5em',
    fontFamily: 'Raleway',
    marginBottom: '0',
    textAlign: 'left',
    backgroundColor: '#03A9F4'
  },
  slogan: {
    fontWeight: '200',
    fontSize: '1.4em',
    lineHeight: '2em',
    fontFamily: 'Roboto'
  },
  image: {
    backgroundColor: '#03A9F4'
  },
  bottonbox: {
    textAlign: 'left'
  },
  footnote: {
    paddingTop: '20px',
    fontWeight: '200',
    fontFamily: 'Roboto',
    fontSize: '0.85em'
  }
};

export default class Signup extends Component {

  constructor(props) {
    super(props)
    let state = {}
    for (let field of ['email', 'username', 'password', 'rePassword']) {
      state[field] = {value: '', message: '', showValidation: false}
    }
    this.state = state
    this.__validationData = []
  }

  setFieldState(field, newState) {
    this.setState({[field]: {
      ...this.state[field],
      ...newState
    }})
  }

  handleValidation = (field) => ({validationResult, showValidation}) => {
    this.__validationData.unshift({validationResult, showValidation})
    let {message, showValidation: show, valid} = {...this.state[field]}

    if (validationResult != null) {
      valid = validationResult.valid
      let {error, rule} = validationResult
      if (valid == null) message = 'Validating...'
      if (valid === true) message = 'Valid!'
      if (valid === false) message = `Invalid (rule: ${rule}, error: ${error})`
    }

    show = showValidation != null ? showValidation : show

    this.setFieldState(field, {message, showValidation: show, valid})
  }

  showValidation = (field) => () => {
    this.setFieldState(field, {showValidation: true})
  }

  renderMessage(field) {
    let {showValidation, message} = this.state[field]
    return showValidation ? message : null
  }

  allValid() {
    for (let field of ['email', 'password', 'rePassword']) {
      if (this.state[field].valid === false) return false
    }
    return true
  }

  showAllValidations() {
    for (let field of ['email', 'password', 'rePassword']) {
      this.showValidation(field)
    }
  }

  renderField(name, label, data) {
    let {value, valid, message, showValidation} = data
    let style
    if (showValidation && valid === true) style = 'success'
    if (showValidation && valid === false) style = 'error'

    let handleChange = (e) => {
      this.setFieldState(name, {value: e.target.value})
    }

    return (
      <TextField
        // hintText="bourguiba"
        floatingLabelText={label}
        id={name}
        name={name}
        value= {value}
        onChange={handleChange}
        onBlur={this.showValidation(name)}
        fullWidth={true}
        errorText={showValidation ? message : null}
      />
    )
  }

  handleChangeRegisterFields(event) {
    event.preventDefault();
    this.setState({[event.target.name]: event.target.value});
  }

  handleSubmit(event) {
    event.preventDefault();
    this.props.onSubmit(
      this.state.email,
      this.state.username,
      this.state.password,
      this.state.agree
    )
  }


  render() {
    let {
      email: {value: email},
      password: {value: password},
      rePassword: {value: rePassword}} = this.state

    return (
      <div>
        <div className="row middle-xs center-xs">
          <div className="col-xs-12
                col-sm-8
                col-md-6
                col-lg-4">
            <div className="box left-xs">
              <img src="/img/logo/onehealth_gray.svg" alt="OneHealth" style={ styles.logo }/>
            </div>
          </div>
        </div>
        <div className="row middle-xs center-xs">
          <div className="col-xs-12
              col-sm-8
              col-md-6
              col-lg-4">
            <div className="box">
              <form onSubmit={this.onSubmit}>
                <Card>
                  <CardTitle title="Devenez membre! C'est gratuit!" titleColor="white" subtitleColor="white" subtitle="on vous attend de l'autre coté de la rive" style={ styles.title }/>
                  <CardMedia style={ styles.image }>
                    <img src="/img/homepage/welcome_card.jpg" />
                  </CardMedia>
                  <CardText style={ styles.box }>

                    <br />
                    {this.renderField('username', 'username', this.state.username)}
                    <Validate onValidation={this.handleValidation('username')} >
                      <IsRequired key="is-required" value={username} />
                      <IsUnique time={1000} value={username} />
                    </Validate>
                    <br/>
                    {this.renderField('email', 'E-mail', this.state.email)}
                    <Validate onValidation={this.handleValidation('email')} >
                      <IsRequired key="is-required" value={email} />
                      <IsEmail key="is-email" value={email} />
                      <IsUnique time={1000} value={email} />
                    </Validate>
                    <br />
                    {this.renderField('password', 'Password', this.state.password)}
                    <Validate
                      onValidation={this.handleValidation('password')}
                      args={{value: password}}
                    >
                      <IsRequired key='is-required' />
                      <HasLength key='has-length' min={6} max={10} />
                      <HasNumber key='has-number' />
                    </Validate>

                    {this.renderField(
                      'rePassword', 'Repeat password', this.state.rePassword)}
                    <Validate
                      onValidation={this.handleValidation('rePassword')}
                      needTouch={[['are-same', 'value1'], ['are-same', 'value2']]} >
                      <AreSame key='are-same' value1={password} value2={rePassword} />
                    </Validate>

                    <br />
                    { state.resultMessage }
                    <br />
                    <br />
                    <Checkbox
                      checked={ this.agree }
                      label="Je confirme que j'ai lu les termes et les conditions d'utilisations."
                    />
                  </CardText>
                  <CardActions style={ styles.bottonbox }>
                    <RaisedButton
                      label="S'enregistrer"
                      onClick={() => this.showAllValidations()}
                      disabled={!this.allValid()}
                      secondary={true}
                    />
                    <br/>
                    <p style={ styles.footnote }>
                      Vous êtes déjà un membre de notre réseaux. Vous pouvez vous <a href="#">connecter</a>.
                    </p>
                  </CardActions>
                </Card>
              </form>
            </div>
          </div>
        </div>
      </div>
    )
  }
};

Signup.propTypes = {
  onSubmit: PropTypes.func.isRequired,
  agree: PropTypes.bool.isRequired,
  username: PropTypes.string.isRequired,
  email: PropTypes.string.isRequired,
  password: PropTypes.string.isRequired
}

Signup.defaultProps = { initialCount: 0 };

Hello, I think it's wrong webpack configuration and, as if so, it's easy enough to solve. Try to omit include option for the babel-loader.

I agree. I have solved the problem by removing include . I think that it should be mentioned that ES6 stage-1 at least is needed to compile the project.