Search code examples
javascriptpolymerpolymer-3.x

How to make mixin populate state ES6 module?


After _getUserProfile() is ran and the host properties are populated, other elements that use UserProfileMixin are not getting the properties that have been populated, they are only getting non-populated defaults. Like this.profile will be {} instead of the profile.

Why is this and how can I have this mixin populate the es6 module user-profile-state.js from with in the mixin?

Note: Not interested in using Redux, I am happy with ES6 modules as state management. Only in Mixins is there a issue.

% cat app/account/user-profile-state.js 
const profile = {};
let isLoggedIn = false;
let profilePic;

export {
  isLoggedIn,
  profile,
  profilePic,
};

% cat app/account/user-profile.js 
import {html, PolymerElement} from '@polymer/polymer/polymer-element.js';
import '@polymer/paper-button/paper-button.js';
import { PauseForRipple } from '../mixins/pause-for-ripple-mixin.js';
import { FetchMixins } from '../mixins/fetch-mixins.js';

import { HOST } from '../constants.js';
import { UserProfileMixin } from '../mixins/user-profile-mixin.js';

import {
  isLoggedIn,
  profile,
  profilePic,
} from '../account/user-profile-state.js';


class UserProfile extends UserProfileMixin(FetchMixins(PauseForRipple(PolymerElement))) {
  static get template() {
    return html`
      <style>
        :host {
          display: flex;
          align-items: center;
          justify-content: center;
          flex-direction: column;
          padding: 10px;
          height: 100%;
        }

        .login-text, .login-text-small {
          color: var(--primary-text);
          font-size: 25px;
          font-weight: 300;
        }

        .login-text-small {
          font-size: 15px;
        }

        --paper-input-container-color: red;

        .login-container {
          width: 250px;
          height: 100%;
          padding: 25px;
          display: flex;
          justify-content: center;
        }

        paper-material {
          height: 100%;
          border-radius: 2px;
        }

        paper-button {
          background-color: #fff;
          color: var(--button-text);
          width: 190px;
          font-size: 12px;
        }

        a {
          text-decoration: none;
        }
      </style>

      <div>First Name: [[profilePic]]</div>

    `;
  }

    static get properties() {
      return {
        isLoggedIn: {
          type: Boolean,
          value: isLoggedIn,
        },

        profile: {
          type: Object,
          value: profile,
        },

        profilePic: {
          type: String,
          value: profilePic,
        },

      };
    }


  ready() {
    super.ready();
    console.log(this.profile);
    console.log(this.isLoggedIn);
  }

}

% cat app/mixins/user-profile-mixin.js 
import { dedupingMixin } from '@polymer/polymer/lib/utils/mixin.js';
import { USER_PROFILE } from '../constants'; // host url
import {
  isLoggedIn,
  profile,
  profilePic,
} from '../account/user-profile-state.js';

let rawUserProfileMixin = (base) => {
  class foo extends base {
    constructor() {
      super();
    }

    static get properties() {
      return {
        // this is for host url
        USER_PROFILE: {
          type: String,
          value: USER_PROFILE,
        },

        isLoggedIn: {
          type: Boolean,
          value: isLoggedIn,
        },

        profile: {
          type: Object,
          value: profile,
        },

        profilePic: {
          type: String,
          value: profilePic,
        },

      };
    }

    _getUserProfile() {
      var url = `${this.HOST}${this.USER_PROFILE}`;
      var request = this.createRequest(url);

      fetch(request)
        .then(this.fetchError)
        .then(this.json)
        .then((response) => {
          if (response.profile) {
            console.log('aaa');
            this.isLoggedIn = true;
            this.profilePic = response.profile.pic;
            this.profile = Object.assign({}, response.profile);
          }
        })
        .catch((e) => {
          this.isLoggedIn = false;
          console.log('error in checking logged in mixin ' + e);
        });
    }

    ready() {
      super.ready();
    }
  }
  return foo;
};

export const UserProfileMixin = dedupingMixin(rawUserProfileMixin);

Solution

  • The solution is to make a accessor function(see airbnb JS style guide).

    let profile = {};              
    let isLoggedIn = false;
    let profilePic;
    
    const setProfile = (newValue) => {
      if (newValue) {
        profile = Object.assign({}, newValue);
        isLoggedIn = true;
        profilePic = profile.pic;
      } else {
        profile = null;
        isLoggedIn = false;
        profilePic = null;
      }
    }
    
    export {
      isLoggedIn,
      profile,
      profilePic,
      setProfile,
    };
    

    Mixin:

    import {
      isLoggedIn,
      profile,
      profilePic,
      setProfile,
    } from '../account/user-profile-state.js';
    
    
    let rawUserProfileMixin = (base) => {
      class foo extends base {
        constructor() {
          super();
        }
    
        static get properties() {
          return {
            // this is for host url
            USER_PROFILE: {
              type: String,
              value: USER_PROFILE,
            },
    
            isLoggedIn: {
              type: Boolean,
              value: isLoggedIn,
            },
    
            profile: {
              type: Object,
              value: profile,
            },
    
            profilePic: {
              type: String,
              value: profilePic,
            },
          };
        }
    
        _getUserProfile() {
          var url = `${this.HOST}${this.USER_PROFILE}`;
          var request = this.createRequest(url);
    
          fetch(request)
            .then(this.fetchError)
            .then(this.json)
            .then((response) => {
              setProfile(response.profile);
            })
            .catch((e) => {
              this.isLoggedIn = false;
              console.log('error in checking logged in mixin ' + e);
            });
        }