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

Can't set this nested object in a immutable record correctly

设置平面对象不可变记录没有问题。但是现在我有一个问题,我想设置一个记录,我想也许是一个记录列表?我正在尝试将我的 User ref 在我的 firebase 数据库中放入一个或多个不可变记录中。

所以我从 firebase 加载我的用户参考。它的结构看起来像。

我不知道如何嵌套列表。用户有一个 UID 列表。从那里它变得更加平坦。但这甚至可能有一个记录列表吗?我还没有在网上看到任何例子,所以我现在迷路了。任何帮助将不胜感激。

如果我在做一些更讨人喜欢的事情,比如个人资料,它看起来会是这样。

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

似乎通过 UID 列表是我很难通过的第一个挑战。一旦超过了最初的列表,它就会变得更加平坦。

也许我什至不应该做这个不可变的。我对其他建议如何处理这些数据持开放态度。此时我只是习惯在我的应用程序中使用不可变记录。我希望在最后一点坚持这种模式。

目前基本上还没有记录列表。据我所知,您可以使用带有记录值的地图并根据 答案扩展 Record class 以获得与您想要的等效的内容(下面的代码基于这种方法)。

我还可以找到一篇有趣的文章,其中有多种方法,以实用的方式实现相同的想法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>

Shyams 的建议完全正确,所以这是公认的答案。如果您有需要,大多数人应该能够采用它。但是,如果您像我一样,并且将 firebase 与 redux 和选择器一起使用,这就是 Shyams 建议对我有用的方式。我并不是说它是您所见过的最纯粹的 react/redux/selectors 示例,但它对我有用。

事不宜迟。

最初我从 redux action 和 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
  };
}

在 reducer 中,为了将所有深度嵌套的数据正确 return 到我使用的连接组件,我使用了 fromJS。也许有更好的方法来做到这一点,但这对我有用。

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 到 props

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

这是我们整齐深层嵌套的不可变混沌的最终证明。 :)