Как заставить миксин заполнять модуль состояния ES6?

После запуска _getUserProfile() и заполнения свойств хоста другие элементы, использующие UserProfileMixin, не получают заполненные свойства, они получают только незаполненные значения по умолчанию. Вроде this.profile будет {} вместо профиля.

Почему это так и как я могу заставить этот миксин заполнить модуль es6 user-profile-state.js из миксина?

Примечание. Не заинтересован в использовании Redux, я доволен модулями ES6 в качестве управления состоянием. Только в Mixins есть проблема.

% 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);

person dman    schedule 17.08.2019    source источник


Ответы (1)


Решение состоит в том, чтобы сделать функцию доступа (см. Руководство по стилю airbnb JS).

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,
};

Миксин:

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);
        });
    }
person dman    schedule 17.08.2019