Giter VIP home page Giter VIP logo

mobx-react's People

Contributors

a-gambit avatar andrewbranch avatar andykog avatar bartonhammond avatar benjamingr avatar bnaya avatar capaj avatar danielkcz avatar delaet avatar farwayer avatar fi3ework avatar fredyc avatar jtraub avatar mattruby avatar mweststrate avatar normano64 avatar pioh avatar pustovalov avatar realityforge avatar rossipedia avatar strate avatar sunshine168 avatar timmolendijk avatar tkrotoff avatar urugator avatar venryx avatar vkrol avatar vonovak avatar xaviergonz avatar ynejati 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 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

mobx-react's Issues

Built in support for connecting stores to components

A common pattern I see arising is the need to connect a component to one or many mobx stores.

Currently, you need to write your own higher order component that will fetch these stores. While this isn't a monumental task in itself (as mobx makes this type of thing relatively straight forward), it would be great to have this feature built into mobx-react to promote a standardized method to accomplish this.

Looking to react-redux for inspiration, I see a lot of ideas there that could gracefully transfer over to mobx-react.

One approach is to wrap the application's Root component in a higher order store provider component that will inject application stores into the application's context. Then retrieve stores with an @connect (or similar) decorator that defines which stores should be connected.

Another approach is to "register" stores with react-mobx at their definition. Then, use a similar @connect decorator as described above to fetch one or several registered stores.

I would like to start a discussion as to why this does/doesn't make sense for mobx-react. And if it does make sense, get other thoughts on the table.

(4,36): error TS2503: Cannot find namespace 'React'.

When using Typescript 1.6.2 with mobservable-react, I simply do this:

import {observer} from 'mobservable-react';

However, index.d.ts doesn't have a declaration of React available. So it would give this error:

(4,36): error TS2503: Cannot find namespace 'React'.

Perhaps you have a way to use TS with mobservable-react that isn't apparent?

Convert to simple object

Hi I am storing an object in an mobservable store that represents a React style object so that I can update styles from within my app. When I update it , e.g. change the borderColor and my React component re-renders nothing changes. If I transfer the style props to a regular JS object manually it works.

const theStyle = {...store.currentStyle}

Any idea why?

Can stores return json objects and array directly?

I am doing my first projecdt with Mobservable and I realized that data returned from the store is an observable.

I would like to have the store transform the data to a JSON object/array so that I don't have to call .toJSON() everytime.

Doesn't work in IE 10

The reportRendering method use WeakMap which is not available in IE 10 and the method fails. Preparing simple PR for that.

Shared state for multiples instances of component

Hi,

I have a little component that wraps a button and shows up a "Loading" text if you click the button.
Something like that:

import React, { Component } from 'react';
import { observer } from 'mobx-react';
import { observable } from 'mobx';

@observer
export class AsyncButton extends Component<void, {}> {
  @observable
  private isLoading: boolean = false;

  constructor() {
    super();
    console.log('constructor')
  }

  render () {
    console.log('render', this.isLoading);

    return (
      <Button
        onClick={() => this.isLoading = !this.isLoading}>
        {this.isLoading ? <span>Loading</span> : <span>Click me</span>}
      </Button>
    );
  }
}

ReactDOM.render(
  <div>
    <AsyncButton/>
    <AsyncButton/>
  </div>,
  document.getElementById('root'));

Expected result: two buttons, If I click button 1 text changes to "Loading" and console logs "render,true"
Actual result: two buttons, If I click button 1 text of button 1 and button 2 changes to "Loading" and console logs "render,true" twice. If I click button 1 again both buttons are re-rendered and text changes to "Click me".

Workarounds:

  • remove the export statement from the class definition
  • use extendObservable in the constructor instead of observable

Im using Typescript 1.8.9 (with experimentalDecorators set to true), mobx 2.0.4 and mobx-react 3.0.3

React Native support

Does this lib work with React Native? If not, any idea what it would take to make it work?

`observer(component)` is not correctly recognized by typescript 1.8-beta

Hey. I'm trying out mobservable-react-typescript and I can't get the typescript compiler to accept "const TimerObserver = observer(Timer)" instead of @observer on Timer
I'm getting "Error:(22, 10) TS2604: JSX element type 'TimerObserver' does not have any construct or call signatures." when I try to use <TimerObserver />
If I cast it to any, the code works, just like the JS examples: const TimerObserver = observer(Timer) as any;

Hmm. Appears to be an issue with overload resolution in TypeScript. If I comment out all but the React.ComponentClass<P> overload it compiles.

TypeScript 1.8 beta(edited)
If I move the following overload to the top it works: export function observer<P>(clazz: 

React.ComponentClass<P>): React.ComponentClass<P>;
npm installed mobservable-react-typescript.. got mobservable 1.2.5 and mobservable-react 2.1.4

Prevent rendering

Hey guys,

Is there currently any way to prevent rendering ?
I would need such a feature to optimize my server side rendering, let me explain how it works:

1/ I'm rendering my app in order to feed the stores (API call...)
2/ When all the stores are ready, I'm rendering my app a second time in order to get the final html
3/ I'm sending the html

With this feature I would be able to prevent the components rendering in the part 1/ for performance improvements ! : )
Do you think we could implement this feature ? I guess we may only have to add a condition in the shouldComponentUpdate lifecycle method ?

Thanks

automatic tracking not working for nested objects?

I took the sample code from the documentation here and modified it a bit to use an object instead of an array for the todos field:

var todoStore = observable({
    todos: { },
    identity: function() { return this.todos; },
    derived: function() {
        let counter = 0; for(let key in this.todos) { ++counter; } return counter;
    }
});

const print = function() {
    console.log(
        JSON.stringify(todoStore.todos),
        JSON.stringify(todoStore.identity),
        todoStore.derived
    );
};

autorun(print);
// -> prints: { } { } 0

todoStore.todos.test = { title: "Take a walk", completed: false };
// -> should print: {"test":{"title":"Take a walk","completed":false}}
//      {"test":{"title":"Take a walk","completed":false}} 1

todoStore.todos.test.completed = true;
// -> should print: {"test":{"title":"Take a walk","completed":true}}
//      {"test":{"title":"Take a walk","completed":true}} 1

Now the whole automatic tracking doesn't work anymore. The places marked with -> should print: ... do not print.

It I add another print(); call at the end of the sample code it prints this:

{"test":{"title":"Take a walk","completed":true}}
     {"test":{"title":"Take a walk","completed":true}} 0

Note the wrong 0 at the end, since this should be 1!

Do I miss something here? Do I need to use mobservable for objects differently from how I would use it intuitively?

mobx-react 3.0.4 breaks mobx-reactive2015-demo

onCanvasClick (in canvas.js) is not invoked on mouse click. Works fine when I downgrade to mobx-react 3.0.3.

Here's my package versions:

node 4.2.2
npm 2.14.7

├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
└── [email protected]

Error when unmounting component has componentWillMount() without componentWillUnmount() method defined

Uncaught TypeError: Cannot read property 'forEach' of undefined

Error references to line 94 in node_modules/mobservable-react/index.js, that states

this.__$mobDependencies.forEach(function(dep) {
    dep.setRefCount(-1);
});

This happens when component has @observer decorator and has own componentWillMount() defined but does not have own componentWillUnmount(). Adding empty componentWillUnmount() method to component makes the error go away.

Maximum Stack Size Exceeded

I made a simple application that has a store structured something like this:

{
  tableData: []
  ,sortColumn: 0
  ,headerTypes: [Number, Date, String, String, String]
}

All of that is observable. I then made a computed view of the table data:

@computed get sortedData() {
    return this.tableData.sort(this.getSortFn(this.sortType, this.sortColumn));
  }

I then fill the tableData with ~10000 items that contains data like:

[0, new Date(), "foo", "foo", "foo"]

and I render it out via:

import React, { Component, PropTypes } from 'react';
import {observer} from "mobs-react";
import Row from './Flexbox/Row.jsx';
import Col from './Flexbox/Col.jsx';
import Box from './Flexbox/Box.jsx';
import DemoListItem from './DemoListItem.jsx';
import store from '../Store/DemoTableStore.jsx';

observer
class DemoTableListItemsView extends Component {
  render() {
    let table = [];
    const { tableData } = this.props;

    for(var i=0, end=tableData.length; i<end; ++i) {
      table.push(<DemoListItem key={tableData[i][0]} data={tableData[i]}/>);
    }

    return <div>{table}</div>;
  }
}

@observer
class DemoTable extends Component {

  constructor(props) {
    super(props);
  }

  render() {
    return (
      <div style={{ margin: 20, backgroundColor: '#E4E4E4' }}>
        <Row style={{ width: '100%', left: 16, backgroundColor: '#A4A4A4', margin: 0 }}>
          <Col className="col-xs">
            <Box border={0}>
              <p style={{ textAlign: 'center', borderRadius: '0.2em' }}>
                  <span>Number</span>
              </p>
            </Box>
          </Col>
          <Col className="col-xs">
          <Box>
              <p style={{ textAlign: 'center', borderRadius: '0.2em' }}>
                  <span>Date</span>
              </p>
          </Box>
          </Col>
          <Col className="col-xs">
          <Box >
              <p style={{ textAlign: 'center', borderRadius: '0.2em' }}>
                  <span >String</span>
              </p>
          </Box>
          </Col>
          <Col className="col-xs">
          <Box >
              <p style={{ textAlign: 'center', borderRadius: '0.2em' }}>
                  <span >Info1</span>
              </p>
          </Box>
          </Col>
          <Col className="col-xs">
          <Box >
              <p style={{ textAlign: 'center', borderRadius: '0.2em' }}>
                  <span >Info2</span>
              </p>
          </Box>
          </Col>
        </Row>
        {/*Recommended pattern by mobx, rendering a list with a component who's only job is to render the list*/}
        <DemoTableListItemsView tableData={store.sortedData}/>
      </div>
    );
  }
}

export default DemoTable;

Trying to change my sort column, I get this spewing out from mobx:

[Error] RangeError: Maximum call stack size exceeded.
  quickDiff (bundle.js:39528)
  bindDependencies (bundle.js:38499)
  trackDerivedFunction (bundle.js:38485)
  trackAndCompute (bundle.js:38425)
  onDependenciesReady (bundle.js:38399)
  notifyDependencyReady (bundle.js:38468)
  (anonymous function) (bundle.js:38586:93)
  forEach
  propagateReadiness (bundle.js:38586)
  propagateAtomReady (bundle.js:38314)
  reportReady (bundle.js:38350)
  reportChanged (bundle.js:38335)
  set (bundle.js:39349)
  (anonymous function) (bundle.js:39297)
  sortColumn (bundle.js:147)
  (anonymous function) (bundle.js:203)
  handleMouseUp (bundle.js:15937)
  (anonymous function)
  dispatchEvent
  invokeGuardedCallback (bundle.js:50174)
  executeDispatch (bundle.js:42419)
  executeDispatchesInOrder (bundle.js:42439)
  executeDispatchesAndRelease (bundle.js:41890)
  executeDispatchesAndReleaseTopLevel (bundle.js:41901)
  forEach
  forEachAccumulated (bundle.js:56402)
  processEventQueue (bundle.js:42063)
  runEventQueueInBatch (bundle.js:50201)
  handleTopLevel (bundle.js:50212)
  handleTopLevelImpl (bundle.js:50290)
  perform (bundle.js:55852)
  batchedUpdates (bundle.js:48863)
  batchedUpdates (bundle.js:53572)
  dispatchEvent (bundle.js:50367)
  (anonymous function)

I understand 10000 rows is a lot, but why would it only explode on a computed sort? I can keep inserting more elements without any issues. Let me know if I need to be clearer or if more code is needed.

Windows: refusing to install mobx-react as a dependency of itself

I can't install mobx-react on Windows 7 Enterprise SP1. I can install it on OS X but not on Windows.

>npm install mobx-react --save
npm ERR! Windows_NT 6.1.7601
npm ERR! argv "C:\\Program Files\\nodejs\\node.exe" "C:\\Program Files\\nodejs\\node_modules\\npm\\bin\\npm-cli.js" "install" "mobx-react" "--save" npm ERR! node v6.1.0
npm ERR! npm  v3.8.6
npm ERR! code ENOSELF

npm ERR! Refusing to install mobx-react as a dependency of itself
npm ERR!
npm ERR! If you need help, you may report this error at:
npm ERR!     <https://github.com/npm/npm/issues>

npm ERR! Please include the following file with any support request:
npm ERR!     C:\Users\hipertracker\IdeaProjects\mobx-react\npm-debug.log

npm-debug.log:

0 info it worked if it ends with ok
1 verbose cli [ 'C:\\Program Files\\nodejs\\node.exe',
1 verbose cli   'C:\\Program Files\\nodejs\\node_modules\\npm\\bin\\npm-cli.js',
1 verbose cli   'install',
1 verbose cli   'mobx-react',
1 verbose cli   '--save' ]
2 info using [email protected]
3 info using [email protected]
4 silly loadCurrentTree Starting
5 silly install loadCurrentTree
6 silly install readLocalPackageData
7 silly fetchPackageMetaData mobx-react
8 silly fetchNamedPackageData mobx-react
9 silly mapToRegistry name mobx-react
10 silly mapToRegistry using default registry
11 silly mapToRegistry registry http://registry.npmjs.org/
12 silly mapToRegistry data Result {
12 silly mapToRegistry   raw: 'mobx-react',
12 silly mapToRegistry   scope: null,
12 silly mapToRegistry   name: 'mobx-react',
12 silly mapToRegistry   rawSpec: '',
12 silly mapToRegistry   spec: 'latest',
12 silly mapToRegistry   type: 'tag' }
13 silly mapToRegistry uri http://registry.npmjs.org/mobx-react
14 verbose request uri http://registry.npmjs.org/mobx-react
15 verbose request no auth needed
16 info attempt registry request try #1 at 3:56:28 PM
17 verbose request id 682d08b0672ae9fc
18 verbose etag "4Y5349DQ1M6XWB3P1ZMCABHTT"
19 http request GET http://registry.npmjs.org/mobx-react
20 info retry will retry, error on last attempt: Error: unexpected end of file
21 info attempt registry request try #2 at 3:56:38 PM
22 verbose etag "4Y5349DQ1M6XWB3P1ZMCABHTT"
23 http request GET http://registry.npmjs.org/mobx-react
24 http 304 http://registry.npmjs.org/mobx-react
25 verbose headers { server: 'CouchDB/1.5.0 (Erlang OTP/R16B03)',
25 verbose headers   etag: '"4Y5349DQ1M6XWB3P1ZMCABHTT"',
25 verbose headers   'content-type': 'application/json',
25 verbose headers   'cache-control': 'max-age=300',
25 verbose headers   'accept-ranges': 'bytes',
25 verbose headers   date: 'Fri, 13 May 2016 14:56:38 GMT',
25 verbose headers   via: '1.1 varnish',
25 verbose headers   'x-served-by': 'cache-jfk1036-JFK',
25 verbose headers   'x-cache': 'MISS',
25 verbose headers   'x-cache-hits': '0',
25 verbose headers   'x-timer': 'S1463151398.759860,VS0,VE33',
25 verbose headers   vary: 'Accept-Encoding',
25 verbose headers   connection: 'Keep-Alive',
25 verbose headers   age: '0' }
26 silly get cb [ 304,
26 silly get   { server: 'CouchDB/1.5.0 (Erlang OTP/R16B03)',
26 silly get     etag: '"4Y5349DQ1M6XWB3P1ZMCABHTT"',
26 silly get     'content-type': 'application/json',
26 silly get     'cache-control': 'max-age=300',
26 silly get     'accept-ranges': 'bytes',
26 silly get     date: 'Fri, 13 May 2016 14:56:38 GMT',
26 silly get     via: '1.1 varnish',
26 silly get     'x-served-by': 'cache-jfk1036-JFK',
26 silly get     'x-cache': 'MISS',
26 silly get     'x-cache-hits': '0',
26 silly get     'x-timer': 'S1463151398.759860,VS0,VE33',
26 silly get     vary: 'Accept-Encoding',
26 silly get     connection: 'Keep-Alive',
26 silly get     age: '0' } ]
27 verbose etag http://registry.npmjs.org/mobx-react from cache
28 verbose get saving mobx-react to C:\Users\zk4lo9p\AppData\Roaming\npm-cache\registry.npmjs.org\mobx-react\.cache.json
29 verbose correctMkdir C:\Users\zk4lo9p\AppData\Roaming\npm-cache correctMkdir not in flight; initializing
30 silly install normalizeTree
31 silly loadCurrentTree Finishing
32 silly loadIdealTree Starting
33 silly install loadIdealTree
34 silly cloneCurrentTree Starting
35 silly install cloneCurrentTreeToIdealTree
36 silly cloneCurrentTree Finishing
37 silly loadShrinkwrap Starting
38 silly install loadShrinkwrap
39 silly loadShrinkwrap Finishing
40 silly loadAllDepsIntoIdealTree Starting
41 silly install loadAllDepsIntoIdealTree
42 silly rollbackFailedOptional Starting
43 silly rollbackFailedOptional Finishing
44 silly runTopLevelLifecycles Starting
45 silly runTopLevelLifecycles Finishing
46 silly install printInstalled
47 verbose stack Error: Refusing to install mobx-react as a dependency of itself
47 verbose stack     at checkSelf (C:\Program Files\nodejs\node_modules\npm\lib\install\validate-args.js:53:14)
47 verbose stack     at Array.<anonymous> (C:\Program Files\nodejs\node_modules\npm\node_modules\slide\lib\bind-actor.js:15:8)
47 verbose stack     at LOOP (C:\Program Files\nodejs\node_modules\npm\node_modules\slide\lib\chain.js:15:14)
47 verbose stack     at chain (C:\Program Files\nodejs\node_modules\npm\node_modules\slide\lib\chain.js:20:5)
47 verbose stack     at C:\Program Files\nodejs\node_modules\npm\lib\install\validate-args.js:16:5
47 verbose stack     at C:\Program Files\nodejs\node_modules\npm\node_modules\slide\lib\async-map.js:52:35
47 verbose stack     at Array.forEach (native)
47 verbose stack     at C:\Program Files\nodejs\node_modules\npm\node_modules\slide\lib\async-map.js:52:11
47 verbose stack     at Array.forEach (native)
47 verbose stack     at asyncMap (C:\Program Files\nodejs\node_modules\npm\node_modules\slide\lib\async-map.js:51:8)
48 verbose cwd C:\Users\zk4lo9p\IdeaProjects\mobx-react
49 error Windows_NT 6.1.7601
50 error argv "C:\\Program Files\\nodejs\\node.exe" "C:\\Program Files\\nodejs\\node_modules\\npm\\bin\\npm-cli.js" "install" "mobx-react" "--save"
51 error node v6.1.0
52 error npm  v3.8.6
53 error code ENOSELF
54 error Refusing to install mobx-react as a dependency of itself
55 error If you need help, you may report this error at:
55 error     <https://github.com/npm/npm/issues>
56 verbose exit [ 1, true ]

[email protected] wants mobservable@^0.6.9

Could you please update so we can use it with mobservable 0.7.0 ?

Thanks!

npm ERR! argv "/usr/local/Cellar/node/4.1.0/bin/node" "/usr/local/bin/npm" "install" "-d"
npm ERR! node v4.1.0
npm ERR! npm  v2.14.5
npm ERR! code EPEERINVALID

npm ERR! peerinvalid The package [email protected] does not satisfy its siblings' peerDependencies requirements!
npm ERR! peerinvalid Peer [email protected] wants mobservable@^0.6.9

Add changelog

Hi! Thanks for the great lib but it's very inconvenient to track changes between versions.
It would be great either to add CHANGELOG.md or attach this info to new releases.
Thanks!

Destructuring the store

Are there any issues with doing something like this:

import React from 'react';
import { render } from 'react-dom';
import { observer } from 'react-redux';
import { store } from './store';

const App = observer(({ threads }) => (<div>{threads.map(thread => <div>{thread.name}</div>)}</div>);
render(<App {...store} />, document.getElementById('app'));

Rollup error: Module does not export observer

Trying to work mobx-react into one of my projects but I'm having issues getting it to play nicely with Rollup.

 Error: Module c:\Users\cheath\Desktop\front-end\node_modules\mobx-react\index.js does not export observer

Trying to import the lib and decorate a class:

....
import {observer} from "mobx-react";

@observer
class Header extends React.Component {
....

I can seemingly make it work by making the following mods:

//mobx-react/index.js
// Move the export order around.  This project uses Dojo and if the AMD define is before the common we get some issues..
// UMD
 if (typeof exports === 'object') {
    module.exports = mrFactory(require('mobx'), require('react'), require('react-dom'));
 } else if (typeof define === 'function' && define.amd) {
    define('mobx-react', ['mobx', 'react', 'react-dom'], mrFactory);
 } else {
    this.mobxReact = mrFactory(this['mobx'], this['React'], this['ReactDOM']);
 }

And changing my usage in my component to:

 ....
import * as MobX from "mobx-react";

@MobX.default.observer
class Header extends React.Component {
....

Obviously this is a bit of a clunky fix and I am hoping for a better solution.

My Rollup config:

gulp.task("bundle", function () {
return rollup.rollup({
    entry: "./src/main.js",
    plugins: [
        nodeResolve({
            main: true,
            skip: [ "esri" ] // Let Dojo handle Esri
        }),
        commonjs(),
        rollupPostcss({
            plugins: [
                require("autoprefixer"),
                require("precss")
            ]
        }),
        replace({
            "process.env.NODE_ENV": '"development"'
        }),
        babel({
            exclude: "node_modules/**"
        })
    ]
}).then(function(bundle) {
    bundle.write({
        format: "amd", // AMD is Dojo compatible
        dest: "build/app/main.js",
        sourceMap: true
    });
})
});

React Native bindings when using router

Really like what mobx is offering. Thank you for sharing.

My first attempt to try the mobx is integrating it with react native app that uses react-native-router-flux. Can't seem to have binding working, pretty sure i am missing something:

1. Router

class RootRouter extends Component {

    render() {
        return(
            <Drawer content={<ControlPanel />}>
                    <View style={layout.layout}>
                        <Router hideNavBar={true} >
                            <Schema name="default" sceneConfig={Navigator.SceneConfigs.FloatFromRight}/> 

                            <Route name="inventoryList" type="replace" wrapRouter={false} component={InventoryList} title="Inventory" />               
                        </Router>
                    </View>
            </Drawer>
        );
    }
}

2. Main component

 class ControlPanel extends Component {
constructor(props) {
        super(props);
        InventoryStore.httpReq();
    }
    showInventoryList() {  
        Actions.inventoryList({store:InventoryStore });
    }

    render() {
        return (
            <View>
                <ScrollView>            
                    <View>
                        <TouchableOpacity  onPress={this.showInventoryList}>
                            <View>
                                <Text>Inventory List</Text>
                            </View>
                        </TouchableOpacity>
                    </View>
                </ScrollView>
            </View>
        );
    }   
}

3. The List component

class InventoryList extends Component {
  render() {

        if (this.props.store.isLoading === true) {
            return <View><Text>Loading ...</Text></View>;
        }

    return (            
        <View>
                { this.props.store.inventoryData.map(
                (inventory, idx) => <InventoryView inventory={ inventory } key={ idx } />
                ) }
        </View>
    );
  }
}


@observer
class InventoryView extends Component {
  render() {
    const inventory = this.props.inventory;
    return (
      <View>
        <Text>{inventory.ProjectNumber}</Text>
      </View>
    ); 
  }
}

4. The store

const InventoryStore = observable({
  inventoryData: [],
  isLoading: true
});

InventoryStore.httpReq = function (model) {
        this.isLoading = true;
        fetch('http://www.example.com/api/GetData', {
                method: 'GET',              
            })
            .then((response) => response.json())
            .then((responseData) => {

                this.isLoading = false;
                this.inventoryData = responseData

            })
            .done();

    }

Any idea?

Cannot read property 'render' of undefined

So I was switching my project to typescript and in this process I got Cannot read property 'render' of undefined.

After following the stack trace, I ended up in this line.

Debugging showed that componentClass.prototype was undefined, causing it to throw on trying to get a property on undefined. Changing the line to the below fixed everything and all components worked.

if (typeof componentClass === "function" && !componentClass.prototype && !componentClass.isReactClass && !React.Component.isPrototypeOf(componentClass)) {

This is the stack trace, tsconfig, and relevant files

Im not sure if this is a bug on my end or on mobx-react. Right now the "fix" I am using is replacing the line of code, but that isn't very maintainable.

Redundant reevaluation of computed properties used by react components.

Hello!

mobx-react do not track dependencies between components contained in each other
so evaluations of computed props they use are not ordered by mobx stale/ready algorithm.
This means that mobx-react's forceUpdate of parent component can eventually
call render method of child component while it's used @computed's are stale.

More precisely, suppose we have two components A and B where A uses B in it's render metod.
There is also Store with two @computed properties x and y both depending on @observable z.
Component A uses x, component B uses y. Now when z changes the following can happen:
z changes -> x evaluated -> forceUpdate A -> render B -> use y which is stale.

Computed properties x and y are not completely pure in my code, they
can make ajax requests, see this for the reasons.
The problem is that component B queries y multiple times, so many equal ajax
requests can be made. I admit that this violates mobx requirement for @computed props
to be absolutely pure functions, but maybe there is some workaround ? :)
All my other code is very neat without autorun's. And as another argument: many reevaluations of pure functions can also be an overhead.

(great work for mobx, @mweststrate, thank you for sharing it!)

Nested components observing store

Is it ok to use nested components(routes) as observers, when using react-router or something else ? I decorated page with observer and got updates from store, it worked fine for me. Perhaps, there should be some sample or documentation notice about usage with react-router.

Usage with react-dnd

I don't know if this is an 'issue' or just something to be aware of, but I've noticed that when @observer is used with the react-dnd@dragSource decorator (and potentially others) it is important that these are applied in the correct order:

@dragSource(...)
@observer
class MyComponent {
}

If these are the other way around, then some of the optimizations that @observer gives us don't appear to be applied (in particular, the shouldComponentUpdate method doesn't appear to be used).

I haven't look into this much further than confirming that the order matters in my particular situation, and the above appears to be the 'right' way, but I can look into it more if it comes as a surprise.

Can't import a component with @observer

I have the following (toy) component to use in a table:

@observer
class ProgressPus extends Component<{ frac: number }, {}> {
    render() {
        return <div>
                      <p>{this.props.frac}%</p>
                </div>        
    }
}

I define it in the same module as my table, and use it in a table cell like this:

<td><ProgressPus frac={item.progress}/></td>

and everything works fine. However, if I move ProgressPus to a different tsx file and import it into the table file with import {ProgressPus} from 'otherFIle', it now gives the error below. Should I be using a different syntax to import an @observer component?

[mobservable.view 'reactiveRender'] There was an uncaught error during the computation of ComputedObservable[reactiveRender (current value:'undefined')] function reactiveRender() {
                        if (!hasRendered) {
                            hasRendered = true;
                            // withStrict: throw errors if the render function tries to alter state.
                            mobservable.extras.withStrict(true, function() {
                                rendering = baseRender.call(self);
                            });
                        } else {
                            self.__$mobRenderDisposer(); // dispose
                            React.Component.prototype.forceUpdate.call(self);
                        }
                    }ViewNode.computeNextState @ dnode.js:204ViewNode.wakeUp @ dnode.js:168ViewNode.setRefCount @ dnode.js:150(anonymous function) @ core.js:89runAfterTransaction @ dnode.js:44autorun @ core.js:87render @ index.js:51ReactCompositeComponentMixin._renderValidatedComponentWithoutOwnerOrContext @ ReactCompositeComponent.js:587ReactCompositeComponentMixin._renderValidatedComponent @ ReactCompositeComponent.js:607wrapper @ ReactPerf.js:66ReactCompositeComponentMixin.mountComponent @ ReactCompositeComponent.js:220wrapper @ ReactPerf.js:66ReactReconciler.mountComponent @ ReactReconciler.js:37ReactMultiChild.Mixin.mountChildren @ ReactMultiChild.js:241ReactDOMComponent.Mixin._createContentMarkup @ ReactDOMComponent.js:591ReactDOMComponent.Mixin.mountComponent @ ReactDOMComponent.js:479ReactReconciler.mountComponent @ ReactReconciler.js:37ReactMultiChild.Mixin.mountChildren @ ReactMultiChild.js:241ReactDOMComponent.Mixin._createContentMarkup @ ReactDOMComponent.js:591ReactDOMComponent.Mixin.mountComponent @ ReactDOMComponent.js:479ReactReconciler.mountComponent @ ReactReconciler.js:37ReactCompositeComponentMixin.mountComponent @ ReactCompositeComponent.js:225wrapper @ ReactPerf.js:66ReactReconciler.mountComponent @ ReactReconciler.js:37ReactMultiChild.Mixin._mountChildByNameAtIndex @ ReactMultiChild.js:474ReactMultiChild.Mixin._updateChildren @ ReactMultiChild.js:378ReactMultiChild.Mixin.updateChildren @ ReactMultiChild.js:326ReactDOMComponent.Mixin._updateDOMChildren @ ReactDOMComponent.js:871ReactDOMComponent.Mixin.updateComponent @ ReactDOMComponent.js:700ReactDOMComponent.Mixin.receiveComponent @ ReactDOMComponent.js:645ReactReconciler.receiveComponent @ ReactReconciler.js:87ReactChildReconciler.updateChildren @ ReactChildReconciler.js:84ReactMultiChild.Mixin._reconcilerUpdateChildren @ ReactMultiChild.js:216ReactMultiChild.Mixin._updateChildren @ ReactMultiChild.js:351ReactMultiChild.Mixin.updateChildren @ ReactMultiChild.js:326ReactDOMComponent.Mixin._updateDOMChildren @ ReactDOMComponent.js:871ReactDOMComponent.Mixin.updateComponent @ ReactDOMComponent.js:700ReactDOMComponent.Mixin.receiveComponent @ ReactDOMComponent.js:645ReactReconciler.receiveComponent @ ReactReconciler.js:87ReactChildReconciler.updateChildren @ ReactChildReconciler.js:84ReactMultiChild.Mixin._reconcilerUpdateChildren @ ReactMultiChild.js:216ReactMultiChild.Mixin._updateChildren @ ReactMultiChild.js:351ReactMultiChild.Mixin.updateChildren @ ReactMultiChild.js:326ReactDOMComponent.Mixin._updateDOMChildren @ ReactDOMComponent.js:871ReactDOMComponent.Mixin.updateComponent @ ReactDOMComponent.js:700ReactDOMComponent.Mixin.receiveComponent @ ReactDOMComponent.js:645ReactReconciler.receiveComponent @ ReactReconciler.js:87ReactCompositeComponentMixin._updateRenderedComponent @ ReactCompositeComponent.js:562ReactCompositeComponentMixin._performComponentUpdate @ ReactCompositeComponent.js:544ReactCompositeComponentMixin.updateComponent @ ReactCompositeComponent.js:473wrapper @ ReactPerf.js:66ReactCompositeComponentMixin.performUpdateIfNecessary @ ReactCompositeComponent.js:421ReactReconciler.performUpdateIfNecessary @ ReactReconciler.js:102runBatchedUpdates @ ReactUpdates.js:129Mixin.perform @ Transaction.js:136Mixin.perform @ Transaction.js:136assign.perform @ ReactUpdates.js:86flushBatchedUpdates @ ReactUpdates.js:147wrapper @ ReactPerf.js:66Mixin.closeAll @ Transaction.js:202Mixin.perform @ Transaction.js:149ReactDefaultBatchingStrategy.batchedUpdates @ ReactDefaultBatchingStrategy.js:62enqueueUpdate @ ReactUpdates.js:176enqueueUpdate @ ReactUpdateQueue.js:24ReactUpdateQueue.enqueueForceUpdate @ ReactUpdateQueue.js:143ReactComponent.forceUpdate @ ReactComponent.js:86reactiveRender @ index.js:60ObservableView.compute @ observableview.js:57(anonymous function) @ dnode.js:198withStrict @ core.js:301ViewNode.computeNextState @ dnode.js:197ViewNode.notifyStateChange @ dnode.js:182DataNode.notifyObservers @ dnode.js:113DataNode.markReady @ dnode.js:107transaction @ dnode.js:34ListDataModelObservable.setData @ listDataModelObservable.ts:36(anonymous function) @ choresByReact.tsx:237Talker.processHoot @ talker.ts:26(anonymous function) @ talker.ts:11(anonymous function) @ talker.ts:43fire @ jquery.js:3100self.fireWith @ jquery.js:3212done @ jquery.js:8265(anonymous function) @ jquery.js:8606
dnode.js:204 [mobservable.view 'TableView#.1.render()'] There was an uncaught error during the computation of ComputedObservable[TableView#.1.render() (current value:'undefined')] function reactiveRender() {
                        if (!hasRendered) {
                            hasRendered = true;
                            // withStrict: throw errors if the render function tries to alter state.
                            mobservable.extras.withStrict(true, function() {
                                rendering = baseRender.call(self);
                            });
                        } else {
                            self.__$mobRenderDisposer(); // dispose
                            React.Component.prototype.forceUpdate.call(self);
                        }
                    }

React 15

Hey,
Currently using mobx-react is not possible with react 15.
Could you either please update the peerDependencies or (better) merge #33?

index.js should try catch in some method.

index.js
current patch function:

function patch(target, funcName) {
            var base = target[funcName];
            var mixinFunc = reactiveMixin[funcName];
            if (!base) {
                target[funcName] = mixinFunc;
            } else {
                target[funcName] = function() {
                    base.apply(this, arguments);   // (1)
                    mixinFunc.apply(this, arguments);  // (2)
                }
            }
        }

if (1) or (2) throw exception then other observer component will no effect never!

I fix this issues when surround try catch:

       function patch(target, funcName) {
            var base = target[funcName];
            var mixinFunc = reactiveMixin[funcName];
            if (!base) {
                target[funcName] = mixinFunc;
            } else {
                target[funcName] = function() {
                    try {
                        base.apply(this, arguments);
                        mixinFunc.apply(this, arguments);
                    }
                    catch (err) {
                        console.error('mobx-react error ', err);
                    }
                }
            }
        }

another same issues in

var reactiveMixin = {
            componentWillMount: function() {
                ......
                function initialRender() {
                    reaction = new mobx.Reaction(name, function() {
                        if (!isRenderingPending) {
                            isRenderingPending = true;
                            // should surround try catch
                            if (typeof self.componentWillReact === "function")
                                self.componentWillReact();
                            React.Component.prototype.forceUpdate.call(self)
                        }
                    });                
            }
}

Component not updating after ajax call finishes

I have a container component makes about 4 ajax calls after it loads. The calls shoudl update each view accordingly, but it doesn't.

It appears that render is not called when data is received from the server, because when I go to a different route and then come back to this container, the data does show in the view.

Perhaps a complete example of async actions would be helpful.

It is a lot of code, so I will just post here the revelant components

Component that does not update

import React, { PropTypes } from 'react';
import BootTable from './common/boot-table';
import { fetch_trace } from '../stores/trace';

class TraceContainer extends React.Component {

  componentWillMount() {
    fetch_trace(this.props.connectionID);
  }

  render () {

    const colHeaders = [
      {name: 'traceDateTime', label: 'Date/Time'},
      {name: 'traceAction', label: 'Type'},
      {name: 'traceText', label: 'Message'}
    ];

    const { connectionID } = this.props;
    // console.log(this.props.connectionID);
    // console.log(this.context.store.trace.connections[connectionID]);

    const lines = (this.context.store.trace.connections) ? this.context.store.trace.connections[connectionID] : [];

    return (
      <div className="trace">
        <BootTable
          bordered
          condensed
          perPage={10}
          hover
          data={this.context.store.trace.connections[connectionID]}
          colHeaders={colHeaders}
        />
      </div>);
  }
}

TraceContainer.contextTypes = {
  store: PropTypes.object
};

export default TraceContainer;

Contaner component

import React, { PropTypes } from 'react';
import {Tab, Tabs, Label } from 'react-bootstrap';
import { observer } from 'mobservable-react';
import { fetch_hosts } from '../stores/hosts';
import TraceContainer from './trace-container';


const PowerLight = (props) => {

  const light = (props.status == "1") ? <i className="fa fa-circle"></i> : <i className="fa fa-circle-o"></i>;

  return <span className="host-status">{light}</span>;
};

const ConnectionInfo = (props) => {
    const { ConnectionName, IPaddress, IsServer, NumLineTrace, TCPPort, TimeOut } = props;

    const type = (IsServer == "1") ? "Server":"Client";

    return <div className="connection-info">
              <ul className="list-inline">
                <li><Label>Connection Name</Label> {ConnectionName}</li>
                <li><Label>IP</Label> {IPaddress}</li>
                <li><Label>Type</Label> {type}</li>
                <li><Label>Port</Label> {TCPPort}</li>
                <li><Label>Lines</Label> {NumLineTrace}</li>
                <li><Label>Timeout</Label> {TimeOut}</li>
              </ul>
            </div>;

};

class HostTabsContainer extends React.Component {

  componentDidMount() {
    fetch_hosts();
  }

  renderTabs(hosts) {
    return hosts.map((host,i) => {

      const { ID, ConnectionName, Trace } = host;

      const title = <div><PowerLight status={Trace}/> {ConnectionName}</div>;

      return <Tab key={i} eventKey={ID} title={title}>
              <ConnectionInfo {...host}/>
              <TraceContainer connectionID={ID}/>
            </Tab>;

    });
  }

  render () {

    const { hosts } = this.context.store.host;

    return (
      <div className="host-tabs">
        <Tabs defaultActiveKey={1} animation={false}>
          {this.renderTabs(hosts)}
        </Tabs>
      </div>);
  }
}

HostTabsContainer.contextTypes = {
  store: PropTypes.object
};

export default observer(HostTabsContainer);

Main Store

import { observable, autorun } from 'mobservable';
import trace from './stores/trace';
import hosts from './stores/hosts';
import navigation from './stores/navigation';

const appState = observable({
  host: hosts,
  trace: trace,
  navigation: navigation
});

/* a function that observes the state */
autorun(function() {
  console.log(appState);
});

export default appState;

Store that has data relevant to the component

import request from 'superagent';
import _ from 'lodash';
import { observable, autorun } from 'mobservable';

const URL = 'TRACER.wsTraceHCA.cls';

const traceStore = {
  isLoading: true,
  connections: {}
};

export default traceStore;

// ** ACTIONS
export function fetch_trace(connectionID) {
  if (!connectionID) {
    return;
  }

  const query = {
    connectionID
  };

  request.get(URL)
  .query(query)
  .end(function(err,res){
    if (err) {
      console.warn("An error ocurred: ", err);
    }
    else {

      const lines = res.body;

      if (typeof(traceStore.connections.connectionID) == 'undefined') {
          traceStore.connections[connectionID] = [];
      }

      // traceStore.connections[connectionID] = [];
        traceStore.connections[connectionID] = traceStore.connections[connectionID].concat(lines);
        traceStore.isLoading = false;
    }
  });
}

Modifying store prop triggers render, but modified value doesn't persist

I am finding the behaviour to be rather inconsistent, and I think it may have something to do with react-router. I have store variables that when modified, trigger render with the modified values and my views do the right thing, but in some cases that I have not quite pinned down the reason, render gets called but the values in the store don't change. The following is an example of this

Here's my store:

export default class {
  @observable loggedIn = auth.loggedIn()
}

export let connect = Store => Composed =>
  class extends Component {
    render() {
      return <Composed { ...this.props } $ = { new Store() } />
    }
  }

Root component passed to react-router

@connect(Store)
@observer
export default class App extends Component {
  logout = () => {
    this.context.router.replace(`/`)
    this.props.$.loggedIn = false
    console.log('logout', this.props.$.loggedIn) // onClick triggers this first and logs false
  };

  render() {
    let children = Children.map(this.props.children, child => {
      return cloneElement(child, {
        ...child.props,
        ...this.props,
        logout: this.logout,
      })
    })
    console.log('render', this.props.$.loggedIn) // true
    return <div>{ children }</div>
  }
}

...and lastly child component with click method:

export default observer(({
  $,
  logout,
}) =>
  <div>
    { $.loggedIn &&
    <div>
      <a onClick={ logout }>Log out</a>
    </div>
    }
  </div>
)

Most of the time everything works.. .but this does not! Everytime I click logout, the loggedIn observable logs false, triggers render, and inside render remains true

debugging aids?

Are there some more debugging aids available hidden somewhere inside the code?

I would like to track down, why a react component doesn't get updated automatically although it displays an observable value. How would I track down the issue best?

I haven't managed to get a down-stripped version of my issue yet. The following is a small example that is very similar to my case, but this is working as expected:

import React from 'react';
import mobs  from 'mobservable';
import mobsr from 'mobservable-react';
require("mobservable-react-devtools");

const tree = mobs.observable(
    { name: 'root_name', data: 1, collapsed: false, children: [
        { name: 'child_1', data: 2 },
        { name: 'child_2', data: 3, collapsed: false, children: [
            { name: 'child_2_1', data: 4 }
        ] }
    ] }
);

const TreeComponent = mobsr.observer(({ tree }) => {
    const hasChildren  = tree.children && tree.children.length;
    const openClose    = hasChildren ? <span>{tree.collapsed ? '[OPEN] ' : '[CLOSE] '}</span> : null;
    const showChildren = hasChildren && !tree.collapsed;
    return <div>
        <li><span>{openClose}{tree.name}: {tree.data}</span></li>
        {showChildren && <ul>{tree.children.map((c, idx) => <TreeComponent key={idx} tree={c} />)}</ul>}
    </div>;
});

ReactDOM.render(
    <ul><TreeComponent tree={tree} /></ul>,
    document.getElementById('app_id')
);

setInterval(() => { tree.children[0].data = Math.random(); }, 3000);
setInterval(() => { tree.children[1].name = Math.random(); }, 4500);
setInterval(() => { tree.collapsed = !tree.collapsed; }, 7000);
setInterval(() => { tree.children[1].collapsed = !tree.children[1].collapsed; }, 4000);

My case is very similar, except that it doesn't react to changes of collapsed automatically. I need to add the following propTypes definition to make it actually working:

TreeComponent.propTypes = {
    tree: React.PropTypes.shape({
        collapsed: React.PropTypes.bool
    })
}

The bad thing about that is, it stops working again, when switching to production mode, since then react ignores the propTypes definitions.

How would/could I track down the issue best?

Update README with babel plugin ordering

Had a hard time today figuring out why a very simple mobx react sandbox app did not work.

Turned out that the issue was due to the order of babel plugins in my .babelrc.

transform-decorators-legacy has to appear first in the list, otherwise it will break with at least either transform-function-bind or transform-class-properties plugins if they defined before it, with the wrong orders, observables are not triggered at all.

Would be great to update README to clarify this.

Is `autorun` equivalent to `componentWillReact`?

I'm excited about MobX. I was able to reduce the code size significantly by switching from Redux to MobX. Thanks for the great library!

One of the things I usually need in my components is to do some logic whenever a certain prop has changed. Previously, I used to do that logic in componentDidMount and in componentWillReceiveProps. But now I have another source of data: MobX store. Changes happening to mobx data don't trigger componentWillReceiveProps but instead componentWillReact. So now I need to do that logic in componentWillReact as well.

To reduce the number of lifecycle methods I use, I thought of doing:

componentDidMount() {
  autorun(() => this.thatLogic());
}

Is the above equivalent to:

componentDidMount() {
  this.thatLogic();
}
componentWillReact() {
  this.thatLogic();
}

?

My guess is that the autorun solution is even better because it re-triggers the logic based on changes in the data that the logic cares about. As opposed to the latter which re-triggers the logic based on changes in data that the render cares about. Am I correct?

Don't require react-dom

I use a custom react renderer that is not targeting the DOM thus I don't have the react-dom package in my project at all. This ends up giving me this error:

ERROR in ./~/mobx-react/index.js
Module not found: Error: Cannot resolve module 'react-dom' in D:\Code\symphony\node_modules\mobx-react
 @ ./~/mobx-react/index.js 198:8-71

Looking at mobx-react/index.js it doesn't look like react-dom is critical. How about making the package optional and permanently disabling your developer tools unless you have react-dom available?

A future improvement could be to support devtools with an arbitrary react renderer.

Still not in npm

Should I use mobservable-react with the mobx package for now?

Update: It seems that mobx package is not ready either. I will stick with mobservable-* packages.

React stateless components and render calls

As I understand it, when setState is called in react, the component's render method is called and the component and its children will update the vDOM tree so that reactDOM.render can diff (only that section of the tree) and patch it to the real DOM...

With stateless components wrapped in observer, since they don't have a render method, will reactDOM diff the whole vDOM?

forceUpdate: Can only update a mounted or mounting component.

Hi. I'm getting the warning below in the console log.

My app has a table with a detail view next to it. The detail view shows the selected table row. The table also highlights the row under the mouse. As notifications arrive from the server, some items will disappear from the table. All this works fine, except for the warning.

I think it happens when the mouse is over the selected table row and the selected item disappears as instructed by the server. It looks as though it's trying to then update the detail view, which has disappeared. I'm using react and mobservable in the obvious way, so I'm wondering whether this should be handled differently by mobservable somehow?

warning.js:45 Warning: forceUpdate(...): Can only update a mounted or mounting component. This usually means you called forceUpdate() on an unmounted component. This is a no-op. Please check the code for the undefined component.

warning @   warning.js:45
getInternalInstanceReadyForUpdate   @   ReactUpdateQueue.js:34
ReactUpdateQueue.enqueueForceUpdate @   ReactUpdateQueue.js:135
ReactComponent.forceUpdate  @   ReactComponent.js:86
reactiveRender  @   index.js:60
ObservableView.compute  @   observableview.js:57
(anonymous function)    @   dnode.js:198
withStrict  @   core.js:301
ViewNode.computeNextState   @   dnode.js:197
ViewNode.notifyStateChange  @   dnode.js:182
DataNode.notifyObservers    @   dnode.js:113
DataNode.markReady  @   dnode.js:107
ObservableValue.set @   observablevalue.js:34
ObservableObject.defineReactiveProperty.Object.defineProperty.set   @   observableobject.js:61
ListVModelMasterObservable.setHighlightedId @   listViewModelObservable.ts:182
TableRow.render.React.createElement.onMouseEnter    @   choresByReact.tsx:121
ReactErrorUtils.invokeGuardedCallback   @   ReactErrorUtils.js:71
executeDispatch @   EventPluginUtils.js:79
executeDispatchesInOrder    @   EventPluginUtils.js:102
executeDispatchesAndRelease @   EventPluginHub.js:43
executeDispatchesAndReleaseTopLevel @   EventPluginHub.js:54
forEachAccumulated  @   forEachAccumulated.js:23
EventPluginHub.processEventQueue    @   EventPluginHub.js:259
runEventQueueInBatch    @   ReactEventEmitterMixin.js:18
ReactEventEmitterMixin.handleTopLevel   @   ReactEventEmitterMixin.js:34
handleTopLevelWithoutPath   @   ReactEventListener.js:93
handleTopLevelImpl  @   ReactEventListener.js:73
Mixin.perform   @   Transaction.js:136
ReactDefaultBatchingStrategy.batchedUpdates @   ReactDefaultBatchingStrategy.js:62
batchedUpdates  @   ReactUpdates.js:94
ReactEventListener.dispatchEvent    @   ReactEventListener.js:204

Make shouldComponentUpdate optimalization optional

There is a known issue facebook/react#2517 when shouldComponentUpdate prevents rerendering children components depended on the context. It would be nice to make this optimalization optional for compatiblitiy with non reactive libs e.g react-router and it's Link component (applying active link style depends on the context).

propTypes definitions cause unneeded component updates

Hi,

I have a store with an observable list of items. Each item has an id and an observable value.

In the react part I have a List component and a ListItem component. The ListItem component renders the item’s id and value. Next to the value there is a +1 button that increases the item’s value by 1.

The List and ListItem components are observers.

Without propTypes definitions everything is working as expected. If I add a new item to the list only the List component is updated and if I click the +1 button only that specific item is updated.

If I add propTypes definitions to the List and ListItem components on each +1 button click the List component is also updated for some reason. But if I remove the observable properties from the propTypes definition of the ListItem component everything is working as expected.

Example: https://jsfiddle.net/ppetrov/e6ukjvxo/
Every component has a console.log in its render method.

Am I doing something wrong?

Best regards

how to pass a `store` down a nested component hierarchy?

What is the best/recommended way to pass a store down a nested component hierarchy if I don't want to use a global object for that?

Is there something like the <Provider store={myStore}> mechanism from react-redux. I haven't found anything related to that neither in the docs nor in the test suite...

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.