2016-07-11 6 views
0

Ich arbeite an einer "Einstellungen" -Seite, wo ein angemeldeter Benutzer sein Profilbild ändern kann. Es scheint jedoch, dass Meteor Probleme hat, das profile Attribut für eine user zu finden."user.profile" undefiniert trotz seiner Deklaration in Accounts.createUser()

signup.js (hier ist, wo ich den Benutzer auf die Registrierung und erstellen Sie das Profil Attribut erstellen)

import React, { Component } from 'react'; 
import { browserHistory } from 'react-router'; 

export default class Signup extends Component { 
    handleSubmit(event) { 
    event.preventDefault(); 

    var signupEmail = event.target.signupEmail.value; 
    var signupPassword = event.target.signupPassword.value; 

    if (signupPassword !== '') { 
     Accounts.createUser({ 
     email: signupEmail, 
     password: signupPassword, 
     profile: { 
      avatar: "/user-default.svg" 
     } 
     }, (err) => { 
     err ? (console.log(err.reason)) : browserHistory.push("/app/profile"); 
     }); 
    } 
    } 

    render() { 
    return (
     <div className="login-form"> 
     <form onSubmit={this.handleSubmit}> 
      <div className="input-options"> 
      <input type="text" placeholder="Email" name="signupEmail" /> 
      </div> 

      <div className="input-options"> 
      <input type="password" placeholder="Password" name="signupPassword" /> 
      </div> 

      <button className="login-submit bold">Sign me up!</button> 
     </form> 
     </div> 
    ); 
    } 
} 

profile_settings.js

import React, { Component } from 'react'; 
import { Link } from 'react-router'; 
import reactMixin from 'react-mixin'; 
import ReactMeteorData from 'meteor/react-meteor-data'; 

export default class ProfileSettings extends Component { 
    constructor(props) { 
    super(props); 

    this.state = { 
     avatar: this.props.user.profile.avatar 
    } 
    } 

    getMeteorData(){ 
    return{ 
     user: Meteor.user() 
    } 
    } 

    componentWillMount(){ 
    // we create this rule both on client and server 
    Slingshot.fileRestrictions("avatar", { 
     allowedFileTypes: ["image/png", "image/jpeg", "image/gif"], 
     maxSize: 2 * 500 * 500 
    }); 
    } 

    upload(){ 
    var userId = Meteor.user()._id; 
    var metaContext = {avatarId: userId}; 
    var uploader = new Slingshot.Upload("UsersAvatar", metaContext); 
    uploader.send(document.getElementById('input').files[0], function (error, downloadUrl) { // you can use refs if you like 
     if (error) { 
     // Log service detailed response 
     console.error('Error uploading', uploader.xhr.response); 
     alert (error); // you may want to fancy this up when you're ready instead of a popup. 
     } 
     else { 
     // we use $set because the user can change their avatar so it overwrites the url :) 
     Meteor.users.update(Meteor.userId(), {$set: {"profile.avatar": downloadUrl}}); 
     } 
     // you will need this in the event the user hit the update button because it will remove the avatar url 
     this.setState({avatar: downloadUrl}); 
    }.bind(this)); 
    } 

    formSubmit(){ 
    let avatarUrl = this.state.avatar; 
    Meteor.users.update({_id: Meteor.userId() }, { 
     $set: {profile: avatarUrl} 
    }); 
    } 

    render() { 
    return (
     <div> 
     <div className="sticky-header"> 
      <h3>Settings</h3> 
     </div> 

     <form> 
      <div className="row well"> 
      <div className="col-md-6"> 
       <div className="form-group"> 
       <label htmlFor="exampleInputFile">File input</label> 
       <input type="file" id="input" onChange={this.upload.bind(this)} /> 
       <p className="help-block">Image max restriction: 2MB, 500x500. Cropped: 200x200</p> 
       </div> 
      </div> 
      <div className="col-md-6 utar-r"> 
       <img src={this.state.avatar} height="200" width="200" alt="..." className="img-rounded" /> 
      </div> 
      <div className="form-group"> 
       <button className="btn btn-lg btn-primary btn-block" type="submit" onClick={this.formSubmit.bind(this)}>Update Profile</button> 
      </div> 
      </div> 
     </form> 

     <footer className="sticky-footer"> 
      <Link to="/app/profile"> 
      <button className="profile-edit bg-black"> 
       <h3>Cancel</h3> 
      </button> 
      </Link> 
      <Link to=""> 
      <button className="profile-edit"> 
       <h3>Save Changes</h3> 
      </button> 
      </Link> 
     </footer> 
     </div> 
    ); 
    } 
} 

reactMixin(ProfileSettings.prototype, ReactMeteorData); 

Hier ist der Fehler, den ich bin bekommen: TypeError: Cannot read property 'profile' of undefined

Antwort

0

Der Fehler ist nicht fehlgeschlagen, um einezu findenAttribut, aber sagt, dass es keine user (oder dass user ist undefined) Dies ist genau das, was TypeError: Cannot read property 'profile' of undefined bedeutet.

Es gibt ein paar Fehler im Code:

  • die Rückkehr von getMeteorData unter this.data verfügbar ist und nicht this.props
  • getMeteorData läuft nach constructor so gibt es keine Möglichkeit Meteor Daten im Konstruktor zu bekommen
  • getMeteorData gibt Daten reaktiv zurück und hat wahrscheinlich nicht die gewünschten Daten, wenn Sie die Klasse trotzdem instanziieren
So 210

Ich würde empfehlen, den Behälter/Komponenten-Ansatz, der wie ist:

export default class ProfileSettingsContainer extends Component { 
    getMeteorData(){ 
    return{ 
     user: Meteor.user() 
    } 
    } 
    render() { 
    const user = this.data.user; 
    if (user) { 
     return <ProfileSettings user={user} /> 
    } else { 
     return null; // or what ever placeholder you want while the data is being loaded 
    } 
    } 
} 


class ProfileSettings extends Component { 
    constructor(props) { 
    super(props); 

    this.state = { 
     avatar: props.user.profile.avatar 
    } 
    } 
} 

mit dieser Struktur wird die ProfileSettings instanziiert mit etwas unter props.user

Finnaly,

Meteor.users.update({_id: Meteor.userId() }, { 
    $set: {profile: avatarUrl} 
}); 

sollte

sein
Meteor.users.update({_id: Meteor.userId() }, { 
    $set: {'profile.avatar': avatarUrl} 
}); 

aber das ist nicht verwandt

+0

Hmm das ist seltsam. Ich habe die von Ihnen vorgeschlagenen Änderungen vorgenommen und erhalte nun beim Laden der Seite einen neuen Fehler in der Konsole: 'Eigenschaft 'Benutzer' von undefiniert kann nicht gelesen werden. Dieser Fehler tritt auf, wenn die Zeile 'const user = this.data.user' ausgeführt wird. Irgendwelche Gedanken? Danke für deinen Beitrag! – szier

+0

Haben Sie 'Import {ReactMeteorData} von 'Meteor/React-Meteor-Daten'; importieren Sie reactMixin aus 'react-mixin'; 'und nach ProfileSettingsContainer ' reactMixin (ProfileSettingsContainer.prototype, ReactMeteorData); '? – Guig

+0

Ja und ich bekomme immer noch den gleichen Fehler. Ich bin mir nicht sicher, ob das hilft, aber ich habe die Pakete 'autopublish' und 'unsecure' installiert und ich habe noch keine Veröffentlichungen/Abonnements eingerichtet. Könnte das ein Teil des Problems sein? Auch wenn ich 'Meteor.user()' von der Konsole aus anrufe, erhalte ich ein 'Objekt' mit der korrekten Benutzer-ID und E-Mail-Adresse von dem aktuell angemeldeten Benutzer. – szier