nicolaslopezj/simple-react-form

Client-side code shouldn't be embedded in server-side schema?

JulianKingman opened this issue · 4 comments

I'm using SRF with OnsenUI, and I'm having this issue: in the schema (Simple Schema) I use client-side components as "type" for the srf field (e.g. name: {type: String, srf: {type: TextInput}}). This in turn causes problems as some of the client-side code in OnsenUI can't be executed on the server, which SRF tries to do, since SimpleSchema is isomorphic.

My TextInput field, for example, depends on a script that starts with the following if statement:
if (!window.CustomEvent) {
But unfortunately window doesn't exist on the server.

What's the best approach to handle this?

For now, I edited my field type so instead of doing this:
import {Input} from 'react-onsenui'
I do this:

if(Meteor.isClient){
  Ons = require('react-onsenui');
}
render() {
  <Ons.Input/>
}````

Can you show me more code?

Sure!

Before:

//TextInput.jsx, way simplified
import React, {Component} from 'react';
import {Input} from 'react-onsenui';
//'react-onsenui' depends on 'onsenui', which has a script that calls the window object; 
//This is where I get an error something like "ReferenceError: window is not defined"

export default class TextInput extends Component {
  constructor(props) {
        super(props);
        this.type = props.type || 'text';
        this.state = {value: props.value};
  }

  render(){
    <Input value={this.state.value || ''} type={this.type}/>
  }
}


//Schema.js, simplified for clarity
const Incidents = new Mongo.Collection("incidents");

import {SimpleSchema} from 'meteor/aldeed:simple-schema';
import TextInput from '../../ui/components/FormElements/TextInput.jsx';

let Schemas = {};
Schemas.Incidents = new SimpleSchema({
  Title: {
    type: String,
    srf: {
      type: TextInput
    }
  }
}); 

After:

//TextInput.jsx
import React, {Component} from 'react';
//check if it's the client, I'm using Meteor, so...
if(Meteor.isClient){
  Ons = require('react-onsenui');
}

export default class TextInput extends Component {
  constructor(props) {
        super(props);
        this.type = props.type || 'text';
        this.state = {value: props.value};
  }

  render(){
    <Ons.Input value={this.state.value || ''} type={this.type}/>
  }

}


//Schema.js
const Incidents = new Mongo.Collection("incidents");

import {SimpleSchema} from 'meteor/aldeed:simple-schema';
import TextInput from '../../ui/components/FormElements/TextInput.jsx';

let Schemas = {};
Schemas.Incidents = new SimpleSchema({
  Title: {
    type: String,
    srf: {
      type: TextInput
    }
  }
}); 

Does that clarify things more?

Hm.. I think you are doing it the best way possible 😕