无法在不可变的记录中正确设置此嵌套对象

时间:2018-11-05 15:58:01

标签: javascript reactjs firebase redux immutable.js

设置平面对象不变记录没有问题。但是现在我有一个问题想要设置记录,我想也许是记录列表?我正在尝试将我的Firebase数据库中的User引用添加到一个或多个不可变记录中。

因此,我从firebase加载了用户参考。它的结构看起来像。

enter image description here

我不知道如何嵌套列表。用户具有UID的列表。从那里变得更加讨人喜欢。但这是否有可能有记录列表?我还没有在网上看到任何示例,所以现在我迷路了。任何帮助将不胜感激。

如果我只是在做个人简介之类的事情,那会看起来很像

  export const Profile = Record({
    key: null,
    profileName: '',
    profilePic: '',
    teamName: '', 
  });

似乎很难超越UID列表,这是我遇到的第一个挑战。一旦超过了初始列表,它就会变得讨人喜欢。

也许我什至不应该做这个一成不变的事情。我欢迎其他人建议如何处理此数据。目前,我只是习惯于在应用程序中使用不可变记录。希望我最后一刻都坚持这种模式。

2 个答案:

答案 0 :(得分:1)

基本上没有记录列表。据我所知,您可以将map与记录值一起使用,并根据this的答案扩展Record类,以获取与您想要的等效(以下代码基于此方法)。

我还可以找到一篇有趣的文章,它以一种功能性的方式针对同一想法here采用了多种方法。

如果这不是您所期望的,请告诉我。

var users = {
   'efbluh': {
    'profile': {
      profileName: 'bill',
      profilePic: 'https://blue',
      teamName: 'locals', 
    },
    'team': {
        'Lpphasd' : {
            competitorKey: 'a'
        }
    }
   },
   'fixbluh': {
    'profile': {
      profileName: 'bill',
      profilePic: 'https://blue',
      teamName: 'locals', 
    },
    'team': {
        'Lpphasd' : {
            competitorKey: 'a'
        },
        'asdsadasda' : {
            competitorKey: 'b'
        }
    }
   }
  };

var ProfileRecord = Immutable.Record({
    profileName: '',
    profilePic: '',
    teamName: '', 
  });
var teamRecord = Immutable.Record({
       competitorKey: ''
 });

class User extends Immutable.Record({'profile': new ProfileRecord(), 'team':Immutable.Map()}) {
  constructor({profile, team} = {}) {
    super({team: Immutable.Map(team).map(x=>new teamRecord(x)), profile: new ProfileRecord(profile)})
  }
}

var userMap = Immutable.Map(users).map(x=>new User(x));

// Verify that it's really a record
console.log(userMap.get('efbluh').get('profile').profileName)
console.log(userMap.get('fixbluh').toJS())
console.log(userMap.get('fixbluh').get('team').toJS())
<script src="https://cdnjs.cloudflare.com/ajax/libs/immutable/3.7.4/immutable.min.js"></script>

答案 1 :(得分:0)

羞怯的建议绝对正确,因此这是公认的答案。如果您有需要,大多数人应该可以采用。但是,如果您像我一样,并且将redbase和选择器与firebase一起使用,则这里是Shyams建议对我有效的方式。我并没有声称它是您见过的最纯粹的react / redux / selectors示例,但它对我有用。

事不宜迟。

最初,我是从redux动作和reducer获取用户的。

我的动作和动作创建者从firebase中获取数据,并将其最初存储在我拥有的一些高级firebase db函数中的键值不可变记录中。

import * as types from './actionTypes';
import { Record } from 'immutable';
import { FirebaseList } from 'src/firebase';

export const League = new Record({
  key: null,
  value: null
})

export const leagueFireDB = new FirebaseList({
  onLoad: loadLeagueSuccess,
},League);

export function loadLeague() {
  console.log("LOADLEAGUE::");
  return dispatch => {
    leagueFireDB.path = `users/`;
    leagueFireDB.subscribeChild(dispatch);
  };
}


export function loadLeagueSuccess(league) {
  console.log("LEAGUElOADSuccess::", league);
  return {
    type: types.LOAD_LEAGUE_SUCCESS,
    payload: league
  };
}

在化简器中,为了将所有深层嵌套的数据正确返回到我从JS使用的连接组件。也许有更好的方法可以做到这一点,但这对我有用。

import { Record, fromJS } from 'immutable';
import {
    LOAD_LEAGUE_SUCCESS,
    LOAD_LEAGUE_ERROR,
} from '../actions/actionTypes';

export const LeagueState = new Record({
    key: null,
    value: null
})

export function leagueReducer(state = new LeagueState(), {payload, type}) {
    switch (type) {
        case LOAD_LEAGUE_SUCCESS:
        return state.merge(fromJS(payload));
        
        default:
            return state;
    }

}

在我的联赛页面(一个连接的组件)中,我在mapstate中连接了一个选择器

const mapStateToProps = (state, ownProps) => {
    console.log("MYSTATE::",state)
    return {
        league: LeagueSelector(state),
    }
  }

然后在我的选择器中,通过嵌套接受的答案中指定的记录和地图,完成用户数据的整理。

import { createSelector } from 'reselect';
import { Record, Map } from 'immutable';

var ProfileRecord = Record({
  profileName: '',
  profilePic: '',
  teamName: '', 
});

var teamRecord = Record({
     competitorKey: ''
});

class User extends Record({'profile': new ProfileRecord(), 'team':Map()}) {
  constructor({profile, team} = {}) {
    super({team: Map(team).map(x=>new teamRecord(x)), profile: new ProfileRecord(profile)})
  }
}

export function getLeague(state) {
  return state
}

export function getLeagueList(state) {
  return Map(state.league.value).map(x=>new User(x));
}

//=====================================
//  MEMOIZED SELECTORS
//-------------------------------------

export const LeagueSelector = createSelector(
    getLeague,
    getLeagueList,
);

这是我们整齐地嵌套的不变混乱的最终证明。 :)

enter image description here