Giter Club home page Giter Club logo

react-cursor's Issues

destroy function?

When removing an element from a list I can hand out a cursor to an item in a list to a child component that owns that piece of data. But there is no way for that child component to destroy itself. Instead it needs a callback from the parent or to dispatch a destroy event (it cannot perform this through the cursor).

If we look at cortex, there is a destroy function. Would this make for a good addition to react-cursor?

Details:

  • Every cursor has a destroy function.
  • destroy on an array item removes it from its parent array with $splice
  • destroy on an object value has its parent key removed with $set or $apply
  • destroy on the root position of the cursor will set the cursor to null. Or maybe it is better to throw an exception since I don't know why this would be useful. I only want to use destroy on array elements right now.

Use of the word "orthoganal" in docs

As with programming, it is usually a good idea in language to use the simplest possible solution. Is there a way to communicate what is meant by orthogonal with a more easily understood word? Do you mean that react-cursor and Flux represents opposite approaches?

Batching updates

Are batched updates on the roadmap?

If I understand it correctly, the react batching method for multiple setState() does not
work when called within an ajax request response (or things like setTimeout()).

If multiple updates to a cursor should happen in a ajax response, all calls to
setState would therefore trigger react's render algorithm...

Isn't this a problem?

Avoid using React internal APIs.

In the update method, you are using cmp._reactInternalInstance._pendingStateQueue to get the latest state.

Actually, React provide a setState override accepting function as the first argument to access the latest state. (Its logic is here)

function update(cmp, path, operation, nextValue) {
  this.setState(function (state) {
    if (path.length > 0) {
      return React.addons.update(
        state,
        path.concat(operation).reduceRight(util.unDeref, nextValue)
      );
    } else if (path.length === 0) {
      return nextValue;
    }
  });
}

PS. the current implementation prohibits the root component has its own state. Otherwise, the latest state in queue might be a partial object and not meet the unDeref operations.

Document that react-cursor works with PureRenderMixin

Hi,
I was a bit disappointed when I saw the provided mixin, because it was more work than just using PureRenderMixin if my entire application uses react-cursor for state. But it seems that PureRenderMixin should also work just fine, no? If so, can this be documented in the section discussing the included mixin, and why/when it should be used?
Thanks!

Can we detect and warn on out-of-band mutations?

Prevents #47. I'm not entirely convinced that it's possible to detect out-of-band mutations. I haven't thought it all the way through.

One idea, is that the cursor update methods (set, push, etc.) can hang on to a reference to the final value right before they pass it to react setState. Then in each subsequent invocation to a cursor update method, we can recursively check that the current cursor.value is reference-equal to the previous value at all nodes of the tree, before performing the update. This would have performance implications.

Memory leaks due to heavy memoization

Requires thought to fix.

Specifically, every cursor instance ever created for each (react component, path, value) is forever retained so if we see the same (react component, path, value) we can return the same reference.

Flux? Stores?

How have you been using this in projects? Are you following the normal (as far as there is one) flux pattern where state is broken up into logical domains (named stores) and then each store has a cursor? Or the OM style where they just have one "atom"?

I guess I don't understand how that'd work as it seems having just one root object would make everything get unwieldy as you'd soon have to traverse a long access chain to get the data you want.

So examples of using this would be nice :) (which I'm sure is on your roadmap!)

Using react-cursor through npm

Currently it seems to be not in the npm registry. Adding it to npm would ease up the usage in browserify projects.

πŸ‘ Great work btw!

Convert to es6

We discussed converting to es6, summarizing discussion here.

As of @damassi's change to a webpack build, code is running through babel so we can use es6.

I don't want to lose git blame without a really good reason, so i'd prefer you didn't convert to es6 unless there is a really good reason to do it. if the es6 diff is really small, then its fine. if it changes a lot of lines, id rather wait

Daniel Miladinov: lets wait then, It’d be lots of changes

What about immutable data structures ?

Hello,

React.js and Om amateur speaking here. I'm wondering if your lib could make use of facebool/immutable-js or David Nolen's implementation of ClojureScript immutable data-structures mori. It would basically bring almost all of Om to Javascript, which would be very nice.

Implement default values at a subtree

The problem is that, React state has getInitialState, so the default state can be defined inside the component. With cursors, the default state has to be declared somewhere else, at the top.

So suppose refine could take an optional extra argument, a fallback value

state = {a: {b: null }}

cursor.refine(['a', 'b']).value //=> null
var not_found = {c: {d: 42}}
c2 = cursor.refine(['a', 'b'], not_found);
c3 = c2.refine(['c', 'd']);
c3.value //> 42
c3.set(c3.value + 1); //> {a: {b: {c: {d: 43}}}}

I did implemented this in clojurescript and I found this helped clean up my components quite a bit.

Implement old pendingValue api as stop-gap?

This is not necessary if we implement #53.

I'm working with a client who uses react-cursor, and some of their code broke with the React 13 upgrade because it relied on pendingValue. The new setState api is insufficient because they need to run effects with the pending value, and state updater fns are supposed to be pure, so there is no way to run an effect based on the pending value. This pattern fixes the problem, but some large codebases don't want to rewrite their code. The wingspan codebase also comes to mind as reliant on pendingValue.

Move to individual lodash modules or remove underscore entirely

If interested I may submit a PR - the use of underscore is very small here (partial, omit, union, and every) and could likely easily be removed entirely in favor of a few loops and Function#bind, or at least moved to lodash modules. This would reduce the file size significantly for browserify builds when the host project is not using underscore.

Cursors broken for functions.

Took me hours to figure out, but the following won't work:

// Over consecutive calls...
mycursor.refine("whatever").set(new Function("console.log(" + i + ")")

From what I can see poking around the code, functions don't really seem to figure into the hashing system for the memorizer very well. The strange construction in the above code (new function) is just to show that even when there is not toString equivalence it is still failing. Over consecutive calls the functions will be log(1), log(2), log(3), etc. However, Cursor.build(this) still returns the original log(1) version. If I remove the memorizer factory, everything starts working again.

Cursor.apply is broken after introduce update function

(Fork from #45 )

The update function is introduced in this commit 154b986.

The failing test case details:

1) Cursor should delegate apply method to $apply operation:
     Error: Invariant Violation: update(): expected spec of $apply to be a function; got 8.
      at file:///home/ubuntu/workspace/test/html/js/spec-runner.js:20641
      at update (file:///home/ubuntu/workspace/test/html/js/spec-runner.js:21908)
      at update (file:///home/ubuntu/workspace/test/html/js/spec-runner.js:21915)
      at file:///home/ubuntu/workspace/test/html/js/spec-runner.js:22045
      at file:///home/ubuntu/workspace/test/html/js/spec-runner.js:7544
      at file:///home/ubuntu/workspace/test/html/js/spec-runner.js:7485
      at ReactCompositeComponent_updateComponent (file:///home/ubuntu/workspace/test/html/js/spec-runner.js:14210)
      at file:///home/ubuntu/workspace/test/html/js/spec-runner.js:7406
      at file:///home/ubuntu/workspace/test/html/js/spec-runner.js:15102
      at runBatchedUpdates (file:///home/ubuntu/workspace/test/html/js/spec-runner.js:16926)
      at file:///home/ubuntu/workspace/test/html/js/spec-runner.js:18712
      at file:///home/ubuntu/workspace/test/html/js/spec-runner.js:18712
      at file:///home/ubuntu/workspace/test/html/js/spec-runner.js:16874
      at file:///home/ubuntu/workspace/test/html/js/spec-runner.js:16948
      at ReactUpdates_flushBatchedUpdates (file:///home/ubuntu/workspace/test/html/js/spec-runner.js:14210)
      at file:///home/ubuntu/workspace/node_modules/es5-shim/es5-shim.js:259
      at :1
      at file:///home/ubuntu/workspace/test/html/js/spec-runner.js:18785
      at file:///home/ubuntu/workspace/test/html/js/spec-runner.js:18726
      at file:///home/ubuntu/workspace/test/html/js/spec-runner.js:9890
      at enqueueUpdate (file:///home/ubuntu/workspace/test/html/js/spec-runner.js:16988)
      at enqueueUpdate (file:///home/ubuntu/workspace/test/html/js/spec-runner.js:16504)
      at file:///home/ubuntu/workspace/test/html/js/spec-runner.js:16682
      at file:///home/ubuntu/workspace/test/html/js/spec-runner.js:6620
      at update (file:///home/ubuntu/workspace/test/html/js/spec-runner.js:22056)
      at file:///home/ubuntu/workspace/node_modules/es5-shim/es5-shim.js:259
      at :1
      at file:///home/ubuntu/workspace/test/html/js/spec-runner.js:22212
      at callFn (file:///home/ubuntu/workspace/node_modules/mocha/mocha.js:4562)
      at file:///home/ubuntu/workspace/node_modules/mocha/mocha.js:4555
      at file:///home/ubuntu/workspace/node_modules/mocha/mocha.js:4974
      at file:///home/ubuntu/workspace/node_modules/mocha/mocha.js:5079
      at next (file:///home/ubuntu/workspace/node_modules/mocha/mocha.js:4899)
      at file:///home/ubuntu/workspace/node_modules/mocha/mocha.js:4909
      at next (file:///home/ubuntu/workspace/node_modules/mocha/mocha.js:4844)
      at file:///home/ubuntu/workspace/node_modules/mocha/mocha.js:4876
      at timeslice (file:///home/ubuntu/workspace/node_modules/mocha/mocha.js:6483)

What does the refine method do?

Hi, I am new to the cursor concept and have not used Om yet, but I like very much the general idea and think it it looks very useful when dealing with data in React. I'm not entirely clear, however, what the refine method is doing. It would be great if you could provide (at your leisure of course) any more documentation/explanation about what the refine method is doing. It seems quite central.

Thanks for this great library.

improve build targets

Need separate targets for
UMD
UMD-min
lib (es5, not min)
lib-min

see redux package.json for someone who did this well

Support map(), filter(), find() and forEach() on cursors

One of the things I miss from Cortex is the ability to use map(), filter(), find(), findIndex(), and forEach() on cursors over lists and keys(), values(), and forEach() on cursors over hashes. These should work like their native equivalents but their return values should be cursors.

For example, I want to pass the currently selected item in a list of hashes down to a child component. The currently selected item is identified by having an attribute selected set to true:

var selected = this.props.someList.find(a => a.selected.val());

With react-cursor, I (think I) have to write:

var _ = require('lodash');

var selectedIndex = _.findIndex(this.props.someList.value, a => a.selected);
var selected = this.props.someList.refine(selectedIndex)

We seem to have operations to mutate the cursor, but only value for accessing it.

Q Re: set handlers at equal paths

Would you mind giving a more in-depth explanation of the following statement? I don't understand what this means (what is a path--a cursor? what is a set handler? what do you mean by path changes?):

Note that to do this correctly, not only do equivalent values at equal paths need to be ===, but set handlers at equal paths also need to be ===. (If the path changes, the DOM event handlers may need to be updated as well, requiring a render.)

API to remove me from parent

During my plays with react-cursor I've often wished I could delete a cursor, removing it from its parent (if it has one). Or am I misunderstanding something in barking up this tree? Say for example we wanted to add a delete button to the Clicker components in the helloworld webapp example. Is there a better way to do that without my imaginary delete API?

I don't get it

I thought Om needs cursors (like Haskell needs zippers) inherently due to the immutable nature of the data structures. You can't "take a pointer" to y, like "myY = x.y", expecting that if someone else mutates "x.y", that your myY will also point to the new value. I think cursors and zippers address this problem of wanting to "take a pointer" in the middle of an immutable data structure.

So I have to wonder, since JS objects are mutable, why do you need cursors? Cortex also goes after this problem of central react state, and it doesn't need cursors -- paths into a data structure -- since with mutable structures you can can just do "a.b" instead of cursor(a).refine('b') or whatever.

Just curious.

Bug related to cacheing/memoizing of old component states

Hi, I'm encountering some trouble with react-cursor. The bug that I'm encountering is in a relatively simple component where I add/remove items from a list. The bug manifests itself in many ways. The simplest is that if I add an item to the list and the try to remove it, the item will not be removed.

When I attempted to debug this by looking into what react-cursor is doing, it appears that the memoize function calculates the hashed key for the new state, in which there are no items in the list, and then checks to see if the hashed key is already in the cache variable. Strangely, the hashed key for the component state with items in the list is the same as the new state without the list, and so the memoize returns the previously cached component that still has the item in the list.

I've been trying to debug this myself, since I'd like to contribute to your project, but have hit a bit of a wall. From what I've found it seems as though there could be a problem in the hash function such that it returns the same value for two different strings. Any suggestions?

Swap AMD for CommonJS

CommonJS seems to be the standard within the React community and users would benefit if the library strove for parity.

Readme is out of date

  • pendingValue api is removed
  • updater methods have new preferred updaterFunction api

As of React 13, can Cursor be decoupled from React components?

One real world issue we have run into, is that when React state is conceptually at the top, but actually it isn't at the top because there's non-react portions of the system above it, engines above it etc

As of React 13, cursor doesn't need to use a react private api anymore, because of the improved setState api. So Cursors really only depend on two things conceptually: a setState function, and a current state value. It doesn't actually have to be a React component anymore.

So given this, I believe I could implement the setState/value api outside of react and backed by regular javascript objects, thus cursors can be constructed above the React entry point. This is analogous to the model provided by other cursor implementations (ImmutableJS and Baobab), except it keeps the benefits of react-cursor over those approaches - namely, simplicity of code (a lot fewer lines of code), and simplicity of types (no special immutable types, just regular javascript objects)

Could be worth exploring.

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.