GithubHelp home page GithubHelp logo

Comments (19)

geowarin avatar geowarin commented on July 20, 2024 4

Hi!
I just wanted to contribute my two cents to this issue.
First, let me say that I love seamless-immutable and this issue currently prevents me to use it at a massive scale for react applications.
There are two workarounds for this issue:

myImmutableArray.asMutable().map((item,key) => <li key={key}>item.value</li>)

Or, as mentioned above:

_.map(myImmutableArray, (item,key) => <li key={key}>item.value</li>)

In my opinion, we are loosing the notion of "seamless" here.
I'm setting up projects for people new to React to get them started easily.
Basically, I will tell them: "This is seamless until you use it in a React component".
That's a leaky abstraction.

I wonder if the use case of mapping elements to another immutable collection is as frequent as you think.
By mapping elements, you are basically transforming your Array<X> to another Array<Y>.
So it's a conscious decision and most of the time, I'll be using a transform for read-only operations.

Introducing a mapToImmutable() function and letting map() return a mutable array is another solution to this problem.

What do you think?

from seamless-immutable.

rtfeldman avatar rtfeldman commented on July 20, 2024 3

Fixed and published as 6.0.1! Big ups to @davidblurton for the implementation.

I'm going to wait about a week before announcing this release, so people have a chance to kick the tires and see if we missed anything. 😸

from seamless-immutable.

geowarin avatar geowarin commented on July 20, 2024 1

PR #120 is indeed a great solution!

from seamless-immutable.

sudhakar avatar sudhakar commented on July 20, 2024

What does your Menu component look like? Might be related to #59

from seamless-immutable.

scriptguru avatar scriptguru commented on July 20, 2024

The thing is, it doesn't do anything fancy, and this bug appears with any component

    render() {

        return (
            <ul className="generalMenu">
                {
                    ( this.props.items || [] ).map( ( item ) => <li key={ item.cssClass } className={ item.cssClass }><Link to={ item.link }>{ item.title }</Link></li> )
                }
            </ul>
        );
    }

from seamless-immutable.

sudhakar avatar sudhakar commented on July 20, 2024

Ah.. this.props.items is immutable menu. When you call map, the return value(which is array of react elements) is also casted into immutable see https://github.com/rtfeldman/seamless-immutable/blob/master/src/seamless-immutable.js#L97 same as reported in #59

I havent personally tested it though but it looks like Immutable()-izing React elements causes overflows

from seamless-immutable.

scriptguru avatar scriptguru commented on July 20, 2024

Hm, this is an interesting point. I see what's the problem now, thanks for explanation.

To me it looks like some checks have to be added to seamless-immutable to avoid this issue.

I understand that seamless-immutable hasn't been created for React, but let's face it - it's becoming popular largely thanks to React, so it shouldn't cause extreme problems when being used with it.

React promotes ImmutableJS, which is obviously not as convenient as seamless-immutable, but at least it doesn't cause infinite recursion or something like that.

As a workaround, I think for now I can just use lodash map method, which IIRC doesn't use the native method, but definitely this issue should be addressed since in most examples regarding React usage native methods like map are being used.

UPDATE: as expected, it works fine when using lodash map method.
As I understand, React uses circular references and that's how infinite recursion happens. Probably that's what should be detected, not the React itself (however, detecting React could be an easy first step for solving the problem if the good solution is not obvious).

from seamless-immutable.

sudhakar avatar sudhakar commented on July 20, 2024

IMHO infinite recursion is certainly a bug. Atleast better error should be thrown when circular references are found. Probably you may want to update issue title to get better visibility

from seamless-immutable.

scriptguru avatar scriptguru commented on July 20, 2024

Good idea, thanks

from seamless-immutable.

sudhakar avatar sudhakar commented on July 20, 2024

Oops..Just title change is good enough..It helps to identify in issues list. On first glance, your issue wasn't entirely clear.

BTW, its not a major problem per se. Just that it fails to handle a special case with react. I would simply rephrase it as "Using Map method with react causes infinite loop". (oh pls do remove all bold text in description. Its too noisy)

Also it is not a simple fix. Where references needs to be deeply compared or whatever. Other solution would be to publish methods which will return Mutable data. Again these are major changes that needs to be carefully considered & it might even be against the target goals of the library.

Sorry my last comment was little vague. So lets be nice here ;)

from seamless-immutable.

scriptguru avatar scriptguru commented on July 20, 2024

Yes, I know it's not an easy fix. One of the possible solutions would be to use WeakMap or Map, using all objects that are being converted to immutable as keys, but unfortunately it won't work in older browsers, so it's not really an option. That's why I suggested to include a quick fix that would resolve it just for usage with React, just because it's a major use case.

Or at least a note could be added to the Readme.md on this particular issue, helping people to avoid this problem.

from seamless-immutable.

jedwards1211 avatar jedwards1211 commented on July 20, 2024

I wouldn't recommend using WeakMap or Map even with polyfills...the polyfills aren't perfect and can cause memory leaks in some situations, especially if the same object is used as a key in many different Maps/WeakMaps.

from seamless-immutable.

scriptguru avatar scriptguru commented on July 20, 2024

I think this problem can be solved with one of following approaches or their combination:

  1. Recursion counter. If we go let's say 50 levels deep, it's a bad sign. The counter is basically free for CPU, but cannot really detect circular references - just how deep we are.
  2. Using JSON.stringify() on an object with circular references will throw an error, and this can be used to detect them. However, it will also throw an error in some other cases too - when in encounters something that cannot be converted to JSON. And I guess it's way more expensive than counter.

I think, counter with some reasonable limit, and with possibility to adjust the limit would work the best. Currently a property that is being used as an immutability marker has value true. However, it could store the maximum allowed recursion level, that user can optionally set when making an object immutable.

from seamless-immutable.

jedwards1211 avatar jedwards1211 commented on July 20, 2024

@scriptguru when you use objects as keys with the ES2015 Map polyfill, it just stores the values inside a hidden property tree on the key objects anyway. That's the only way it's possible to simulate object keys in ES5. I think the sole reason old browsers aren't supported is that they don't have an Object.defineProperty method, so the Map data can't be created in a hidden/non-enumerable property.

But that's no matter for this method. All you have to do is temporarily tack the output immutable onto each input object/array in a property with a name that no one's going to use, like _$_$_$immutable, and then remove those properties when done converting the tree into an immutable. I'd be a lot more comfortable with this than with a recursion counter or JSON.stringify() -- the graph structure of the input should be converted to an immutable with the same graph structure, and using a Map or keys on the input objects is the only way to do that.

from seamless-immutable.

rtfeldman avatar rtfeldman commented on July 20, 2024

Yeah, this is a longstanding known issue - see #16 (comment) from 2014 - and I've always worked around it with _.map for React components.

There are two high-level ways to address this:

  1. Don't change the prod build behavior, but in the dev build check for this situation and give a nicer error so it's clearer where you need to use the workaround.
  2. Change both dev and prod to support circular references.

Obviously the latter is massively more work, and I'm wary of what the performance implications might be. 😄

from seamless-immutable.

shamrin avatar shamrin commented on July 20, 2024

I agree with @geowarin that having browser hang and then fail with stack overflow when doing Immutable([1,2,3]).map(function() { return <div /> }) is a very serious issue.

Please consider reviewing two recent approaches to fixing this problem:

  • PR #120 that skips making React components immutable.
  • PR #119 that detects cycles during development and refers to this issue in browser console.

from seamless-immutable.

rtfeldman avatar rtfeldman commented on July 20, 2024

yep, I'm gonna go with both #119 and #120 - left some comments on both 😃

from seamless-immutable.

rtfeldman avatar rtfeldman commented on July 20, 2024

#119 has been merged and released as version 6.0.0; #120 will presumably be 6.0.1 once it's merged.

from seamless-immutable.

davidblurton avatar davidblurton commented on July 20, 2024

Yes, please test it out and mention me if you have any issues.

from seamless-immutable.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.