Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[QUESTION] Observe is only called once instead of everytime something changes in the store #165

Open
MinThaMie opened this issue Sep 7, 2015 · 3 comments
Assignees
Labels

Comments

@MinThaMie
Copy link

The goal is that some items can become favorite and are then rendered in a special list.

But my code does not work cause the observer just works once. Have this problem more often so somehow my implementation of observe isn't correct.

First the user clicks on a listitem with calls upon an action:

export default class LibraryItem extends React.Component {
    constructor(){
        super();
        this._addFavorite = this._addFavorite.bind(this);
    }
    _addFavorite(bid){
        var id = bid;
        libraryBlockActions.addFavorites({ bid : id });
    }

    render() {
//      console.log('render favoritelist state',this.state.favoriteList);
        var bid = this.props.bid;
        return(
            <ListItem primaryText={this.props.title} onTouchTap={this._addFavorite.bind(this, bid)} />
        );
    }

}
export function addFavorites(bidObj) {
    console.log('actionkey:', bidObj);
//  reactor.dispatch(actionTypes.ADD_FAVO, bidObj);
    reactor.dispatch(actionTypes.SWITCH_FAVO, bidObj);
}

This reaches the store:

var favoriteList = [];

function switchFavorite(state, payload, type ) {
    console.log("switched favorites bID:", payload.bid);
    var block = payload.bid;
    if (favoriteList.indexOf(block) === -1) {
        favoriteList.push(block);
        console.log("favolist", favoriteList);
    }
    else {
        var index = favoriteList.indexOf(block);
        favoriteList.splice(index, 1);
        console.log("favolist", favoriteList);
    }
    return favoriteList;
}

class FavoriteStore extends Store {

    constructor(props) {
        super(props);
    }

    getInitialState() {
        return toImmutable([]);
    }

    initialize() {
        this.on(actionTypes.SWITCH_FAVO, switchFavorite);
    }
}

const INSTANCE = new FavoriteStore();
export default INSTANCE;

Getter:

export const favoriteBlocks = [
    ['favoritesList'],
    (favoriteblocks) => {
        console.log('GETTER favoriteblocks',favoriteblocks);
        return favoriteblocks;
    }
];

and then the observer is called:

export default class FavoriteList extends React.Component {
    constructor(){
        super();
        this.state = {
            favoritesList: reactor.evaluate(favoriteListGetters.favoriteBlocks).favoritesList
        };
    }
    componentDidMount() {
        reactor.observe(favoriteListGetters.favoriteBlocks, (favoriteblocks) => {
            console.log('reactor observe favoriteblocks', favoriteblocks);
            this.setState({favoritelist: favoriteblocks});
            console.log('favoritelist:', this.state);
        });
    }
    render() {

        //TODO: Render the items added to the list
        return(
                <div>
                    <List subheader="Favo's" subheaderStyle={{ fontSize: 18}}>
                        {this.state}
                    </List>
                </div>
        );
    }

}
@mindjuice
Copy link

There is no need in Nuclear to call observe() to get the updated state into your component so that it re-renders.

Instead, you just define a getDataBindings(0 function for the component, and whenever the data changes, Nuclear will call setState() for you, thereby causing React to re-render your component.

Remove the observe call (you don't need componentDidMount() here either) and also remove the this.state = {} part from your constructor.

Then, add something like this to your React class:

getDataBindings() {
  return {
    favoritesList: favoriteListGetters.favoriteBlocks
  };
}

Then you can access this.state.favoritesList in your component.

I would also recommend (re)reading the NuclearJS docs on how getters work.

@MinThaMie
Copy link
Author

@mindjuice Thank you for your answer. Sadly it still does not work. I tried rereading the NuclearJS docs, but I don't seem to get the hang of it.
My code now is:


export default class FavoriteList extends React.Component {
    constructor(){
        super();
        this._getDataBindings = this._getDataBindings.bind(this);
        this.state={

        }
    }
    _getDataBindings(){
        return {
            favoritesList: favoriteListGetters.favoriteBlocks
        };
    }
    render() {
        //TODO: Render the items added to the list
        return(
                <div>
                    <List subheader="Favo's" subheaderStyle={{ fontSize: 18}}>
                        {this.state.favoritesList}
                    </List>
                </div>
        );
    }

}

Could you tell me where I go wrong, we could also do this over PM in Gitter if you would prefer that.

@MinThaMie MinThaMie changed the title Observe is only called once instead of everytime something changes in the store [QUESTION] Observe is only called once instead of everytime something changes in the store Sep 8, 2015
@mindjuice
Copy link

I haven't actually used Nuclear with ES6 class syntax. I use createClass() with the mixin instead.

The nuclear-js-react-addons repo has some wrappers and decorators that let you use ES6 syntax with Nuclear, so I'd look there next.

There was also some discussion about this here: #44

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants