-
-
Notifications
You must be signed in to change notification settings - Fork 1.8k
4.0rc2 getIn()
not handling nulls gracefully on Records
#1161
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
This is an intentional breaking change to bring The reason this fails is because there is a value at Note if you change the test code to: const ABRecord = Immutable.Record({ a: null })
const myRecord = new ABRecord()
console.log(myRecord.getIn(['a', 'b'])); That you'll see |
@leebyron Thanks for the detailed explanation, however I believe there is still a bug as the code you posted: const ABRecord = Immutable.Record({a: null});
const myRecord = new ABRecord();
console.log(myRecord.getIn(['a', 'b'])); Also returns:
Additionally, even if this is still intended behavior, I would highly recommend this breaking change get called out specifically on the 4.0 changelog as it was not clear from the current description and it's caused a lot of headaches for us during the upgrade process. |
Ah interesting! I'll definitely make sure there's more tests and clear language around this |
Reopening as a reminder to myself to dig in |
It also happens on nested |
@leebyron would it be possible to have this behavior have a deprecation cycle for one major version where instead of Having a deprecation period with a warning for this will allow us to upgrade sooner and migrate the necessary codepaths with more confidence. |
Same problem with hasIn (Immutable.Map({"sdfsfddfs": null})).hasIn(["sdfsfddfs", "sdfdfs"]);
I hope hasIn will keep his behavior.... |
Will be fixed in the next rc |
Thanks! This is indeed fixed in
Does this mean it will break again in a future version? The handling of nulls is an incredibly useful feature of
Just wanted to get some feedback on the change and what the migration plan is. I'm very curious as to the reasons why this is planned for deprecation. |
The warning is the migration plan. I can’t speak to why it’s planned for deprecation, but this warning should tell you all the callsites to fix before Immutable 5.. |
I'm confused as to the reason this is getting deprecated. There's existing precedent in the JS community that // lodash
const record = { name: { first: 'John', last: 'Brown' } };
_.get(record, 'name.first'); // John
_.get(record, 'name.first.last'); // undefined Otherwise, as it stands in That requires that all deep lookups use chained const record = { a: { b: { c: [{ x: { y: 1 } }] } } };
// currently
const simple = record.getIn(['a', 'b', 'c', 0, 'x', 'y']);
// v4
const complex = record
.get('a', Immutable.Map())
.get('b', Immutable.Map())
.get('c', Immutable.Map())
.get(0, Immutable.Map())
.get('x', Immutable.Map())
.get('y', Immutable.Map()) Chaining I would also think that this approach would open devs up to the potential for errors. For example, right now you can do I hope there's a way around this, because as it stands, the site I maintain would be quite adversely impacted by the removal of the EDIT:
For me and my team, the bigger confusion that sometimes arose was this functionality: const user = { name: { first: undefined: last: null } }; // gotten from an immutable redux store, perhaps
const first = user.getIn(['name', 'first'], 'John'); // Set default
const last = user.getIn(['name', 'last'], 'Doe'); // Set default
console.log(`User's name is: ${first} ${last}`);
// Result: "User's name is undefined null"
// Expected: "User's name is John Doe" It seemed like a bug at first, since we expected the But, we rarely fell into situations where "the silent return of null" was causing issues, since we were typically good about defining default values. The bigger issue was needing to do something like this: const user = { name: { first: null } };
const username = user.getIn(['name', 'first'], 'John'); // this is no good, will return `null`
const better = user.getIn(['name', 'first']) || 'John'; // Returns "John" as expected Basically, sometimes we had to use |
Hey @Kyle-Mendes I think you misunderstand the change. If you test this in v4, you'll find that getIn() with a deeper than existing key will continue to behave as it did before, and notSetValue can be provided to explicitly detect this case separately from a key path that does exist, but just happens to be set to null or undefined. What this change regards is a getIn() path where the path encounters a value which does not support getting - this is almost always indicative of programmer error, which is why we sought to produce early error messages |
Hey @leebyron
As I understand this change, that means that the following is true, right? Attempting to use If this is true, then I disagree with the statement:
In my experience, it is not uncommon for an API to return take this example: const DB = { users: [{ name: 'Kyle', pets: null }] };
function getUserPet(userIndex, petIndex) {
return DB.getIn(['users', userIndex, 'pets', petIndex, 'name'], 'no pet');
}
getUserPet(0,0); // throws warning -- Value at ["pets"] does not have a .get() method: null This, to me, is a real life example that isn't indicative of programmer error necessarily. I don't think it is uncommon for an API to return Now, as I mentioned above, this is much harder to do, and I don't see the gain. I created a simple codepen to show you what I'm encountering: https://codepen.io/Pink401k/pen/NayNPp You can see what I mean in the console. I also included the current Immutable 3 CDN to illustrate that no errors are thrown currently. Thanks for working through this with me. I just hope to illustrate that the current v3 functionality is desirable (at least in some circumstances). I hope that there's a way to keep |
No not that is not the intention as I stated. Please open a bug issue |
@leebyron Will do, thanks again :) |
What happened
After upgrading from
3.x
to4.x
thegetIn()
method is not behaving as before and not as documented. It often returnsInvalid keyPath: Value at ["someKey"] does not have a .get() method: null
instead of handling null keys gracefully.How to reproduce
Returns
But I expected it to return
null
instead.The text was updated successfully, but these errors were encountered: