GithubHelp home page GithubHelp logo

immupdate's Introduction

immupdate's People

Contributors

alexgalays avatar avocadowastaken avatar gbersac avatar gre avatar veloce avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

immupdate's Issues

Missing license

Hi,

Would you please add license information to your library. We are using https://github.com/prometheusresearch/react-forms which has dependency from immupdate which is distributed under MIT license. But license information in immupdate is missing. I'm pretty sure that adding "license": "MIT" to package.json should be enough.

Thanks in advance.

defaultValue is mutated

While using deepUpdate I found out the hard way that the value provided as default was modified in place. I would guess it is not intended behaviour.

with immudate v 1.2.0 (imported via space-lift), I check and this is also the case with 1.2.3.

Here is a small script to reproduce :

const { deepUpdate } = require('immupdate')

const valueToUpdate = { aField: ''}
const defaultValue = { foo: 'aDefaultValue' }
deepUpdate(valueToUpdate)
  .at('otherField')
  .withDefault(defaultValue)
  .at('foo')
  .set('valueChanged!')

// defaultValue.foo is now 'valueChanged!'
console.log(JSON.stringify(defaultValue))

Regression in the type inference of `deepUpdate` return value

For this code:

export function x<STATE>(form: React.Component<{}, STATE>): ChangeHandler<STATE> {
  return (keys: keyof STATE) => (newValue: any) =>
    form.setState<keyof STATE>(state => deepUpdate(state).at(keys).set(newValue))
}

This function compiled with the version 1.2.2 of immupdate, but not with version 1.3.1. I get the following error:

ERROR in /Users/guillaumebersac/projects/ciam-app/frontend/console/common/component/form/changeHandler.ts
./common/component/form/changeHandler.ts
[tsl] ERROR in /Users/guillaumebersac/projects/ciam-app/frontend/console/common/component/form/changeHandler.ts(35,59)
      TS2339: Property 'at' does not exist on type 'Updater<Readonly<STATE>, Readonly<STATE>>'.

It looks like typescript does not infer that the return value of deepUpdate is an ObjectUpdater in this case and not just a Updater.

It looks like the compiler understand the returned object of deepUpdate is an ObjectUpdater, but doesn't take it into account.
Capture d’écran 2020-02-21 à 15 05 15

Would you consider a wrapper/helper?

Maybe an external helper could be bundled with this library, but imported separatedly:

const state = require('immupdate/state')({initial: 76})

state.get() // {initial: 76}
state.update({fruit: 'banana', initial: 84})
state.get('fruit') // 'banana'
state.get() // {initial: 84, fruit: 'banana'}

I've done something like that and was thinking about publishing it as a standalone package depending on immupdate, but perhaps it is better to bundle it here, somewhat like h in bundled into virtual-dom, if more people find this pattern useful.

Breaking change: functions to replace values

I just found out that the latest versions of immupdate don't allow what I call "updater functions" to be passed in the spec object. I find this most regrettable, as I had come to depend on this feature, doing things like:

import {add} from 'ramda'

update(state, { counter: add(1) })

It gave me a super clean and expressive API and I'm absolutely not willing to let go of this style. I understand that you must have your own reasons for this design decision, but I wanted to give you sincere feedback, and for me this change is a deal breaker.

Anyway, I'd be happy to discuss it further if you wish to.

performance issues

I have a tree of object with 6 nodes in total in my tree, and immupdate is extremely slow.

screen shot 2015-10-07 at 23 28 46

(661ms of "Self" on update function)

npmignore build files

I want to use this in a React Native project but its packager tries to compile everything in node_modules, which snags on the .babelrc in this package directory because the project doesn't have the same babel presets installed. Ignoring .babelrc (and the other build files for good measure) and pushing a new version should fix it.

How to delete an element from an array?

I don't know if this is a bug or if I am not using this library correctly.

If I run this code :

deepUpdate(profile)
  .at('addresses')
  .abortIfUndef()
  .at(2)
  .set(immupdate.DELETE)

On this object :

{
  "addresses": [
    {
      "country": "France",
      "default": true,
      "locality": "paris",
      "street_address": "3 avenue du Roi",
      "title": "principale"
    },
    {
      "country": "France",
      "locality": "lille",
      "postal_code": "12345",
      "street_address": "blabla"
    },
    {
      "country": "France",
      "locality": "Niors",
      "postal_code": "85234",
      "street_address": "blabla"
    }    
  ]
}

I get this result (the problem is the trailling null at the end of the array) :

{
  "addresses": [
    {
      "country": "France",
      "default": true,
      "locality": "paris",
      "street_address": "3 avenue du Roi",
      "title": "principale"
    },
    {
      "country": "France",
      "locality": "lille",
      "postal_code": "12345",
      "street_address": "blabla"
    },
    null
  ]
}

Instead of this (which is the result I try to get) :

{
  "addresses": [
    {
      "country": "France",
      "default": true,
      "locality": "paris",
      "street_address": "3 avenue du Roi",
      "title": "principale"
    },
    {
      "country": "France",
      "locality": "lille",
      "postal_code": "12345",
      "street_address": "blabla"
    }
  ]
}

How do we delete an element from an array with immupdate?

Try the sample here : https://repl.it/repls/AdequateDirectVirtualmachines

Problem with deepUpdate of generic objects with version 1.2.0

Came across this problem while updating to the latest version of space-lift today. Great work on that, by the way!

Minimal example

import { deepUpdate } from "immupdate"

function handleChange<T extends object>(values: T, value: T[keyof T], name: keyof T) {
    return deepUpdate(values)
        .at(name)
        .set(value);
};

Test it yourself by downloading this example gist and running npm install && npm run build

Expected result

It compiles, like it did with version 1.1.7

Actual result

example.ts:4:12 - error TS2349: Cannot invoke an expression whose type lacks a call signature. Type '((index: number) => BoundUpdater<T, [T] extends [any[]]
? T[number & keyof T] | undefined : never>) | (<K extends keyof T>(key: K) => BoundUpdater<T, T[K]>)' has no compatible call signatures.

4     return deepUpdate(values)
             ~~~~~~~~~~~~~~~~~~
5         .at(name)
  ~~~~~~~~~~~~~~~~~

Other info

Tested with TypeScript versions 2.8.4, 2.9.2 and 3.0.1, with the same results.

Exception during deepUpdate using withDefault()

Hi there, thanks for the awesome library. I'm not sure if this is a bug or not however i've observed the following when trying to deep update a map using withDefault, which I'd like to use to set default values for an object, just once.

interface Panel {
  id?: string;
  isCollapsed?: false;
}
const DefaultPanel: Panel = { isCollapsed: false};
interface PanelCollection {
    panels: {[panelId: string]: Panel}
}

const initial: PanelCollection = {
  panels: {}
};
const updatedPanel = {id: 'xxxx-xxxxx' };
const updated = deepUpdate(initial).at('panels').at(updatedPanel.id).withDefault(DefaultPanel).modify(p => { return {...p, ...updatedPanel} });

Here is the stacktrace

immupdate.js:96 Uncaught TypeError: Cannot read property 'abort' of undefined
at Updater.cloneForUpdate (immupdate.js:96)
at doModify (immupdate.js:53)
at Updater.modify (immupdate.js:60)
at Object.527 (reducers.ts:48)
at webpack_require (bootstrap f93ece5…:52)
at Object.572 (app.module.ts:78)
at webpack_require (bootstrap f93ece5…:52)
at Object.571 (app.component.ts:104)
at webpack_require (bootstrap f93ece5…:52)
at Object.518 (src async:110)
at webpack_require (bootstrap f93ece5…:52)
at Object.1099 (actions.ts:86)
at webpack_require (bootstrap f93ece5…:52)
at webpackJsonpCallback (bootstrap f93ece5…:23)
at main.bundle.js:1

This however does seem to work, though just less efficiently

deepUpdate(initial).at('panels').at(updatedPanel.id).modify(p => { return {...DefaultPanel, ...p, ...updatedPanel} });

Does this look like an easy fix ?

Union Types

Nice library! I fully agree with what you wrote in the README about "Why Object/Array instead of immutable data structures". I'd love to use it everywhere instead of deeply nested object splice expressions.

What keeps me from completely switching to deepUpdate though is that it does not deal well with union types. For example this:

import { deepUpdate } from 'immupdate'

interface A {
    name: 'a',
    foo: number,
}

interface B {
    name: 'b',
    bar: string,
}

interface Container {
    aOrB: A | B
}

const c: Container = {aOrB: {name: 'a', foo: 1}}

deepUpdate(c).at('aOrB').at('foo').set(2)

results in the following type error for me (using lots of strict flags in tsconfig and Typescript 2.6):

The 'this' context of type 'BoundUpdater<Container, A | B>' is not assignable to method's 'this' of type 'BoundAtUpdater<Container, any[]>'.
    Types of property '__T' are incompatible.
      Type '[Container, A | B]' is not assignable to type '[Container, any[]]'.
        Type 'A | B' is not assignable to type 'any[]'.
          Type 'A' is not assignable to type 'any[]'.
            Property 'includes' is missing in type 'A'.

I mean, raising a compilation error here totally makes sense because there are no typeguards anywhere around .at('foo').

Do you have any thoughts about how one could solve this without giving up too much of the deepUpdate convenience? Is it even possible to use typeguards and generics together in TS?

Bug with .at(0) ?

h1 = {
    "tag": "Group",
    "props": {
        "styles": {
            "display": "flex",
            "flex-direction": "row"
        }
    },
    "children": [
        {
            "props": {
                "class": "employee-name",
                "styles": {
                    "color": "#33cc33"
                },
                "value": "Jane Doe "
            },
            "tag": "Text"
        },
        {
            "props": {
                "class": "employee-photo",
                "url": "http..."
            },
            "tag": "Image"
        }
    ]
}

// Does not work with 0
let h11 = deepUpdate(h1).at('children').at(0).at("props").at("styles").withDefault({}).at('background-color').set('#ffeedd')


// Does work with 1
let h11 = deepUpdate(h1).at('children').at(1).at("props").at("styles").withDefault({}).at('background-color').set('#ffeedd')

My full code atached

tests.txt

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.