[go: up one dir, main page]

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

Dispatching multiple actions doesn't update the component #70

Open
Rommero opened this issue Jul 3, 2019 · 4 comments
Open

Dispatching multiple actions doesn't update the component #70

Rommero opened this issue Jul 3, 2019 · 4 comments

Comments

@Rommero
Copy link
Rommero commented Jul 3, 2019

There's a really annoying bug (or my misunderstanding of storeon conception) which actually prevents from using storeon at all (but I'd really love to :D)
I've created a component with the following code
I've managed to minimize the issue and find the temp solution (which is a terrible one, imho).
So, I have this component

class ArticleContainer extends Component {
  componentDidMount() {   
    this.props.dispatch("articles/get", this.props.id);    
  }

  render() {
    const {      
      isLoading,      
    } = this.props;    

    console.log({isLoading})

    if (isLoading) {
      return <div>isLoading</div>;
    }  

    return <div>loaded</div>
  }
}

export default connect(
  "isLoading",
  ArticleContainer
);

articles/get action looks like this (I reduced the code to the minimum which reproduces the issue)

store.on("articles/get", (state, articleId) => {
    store.dispatch("articles/setLoading", true);    
    store.dispatch("articles/setLoading", false);   
});

store.on("articles/setLoading", (state, isLoading) => {
    return { isLoading };
});

I was expecting the component to have the prop isLoading being updated twice - first set to true and then to false. What I get - is no reaction at all for the component (even that the @changed event was fired properly in storeon)

But! then I changed the code slightly to this

store.on("articles/get", (state, articleId) => {    
  setImmediate(()=>{
    store.dispatch("articles/setLoading", true)
    store.dispatch("articles/setLoading", false)}
  )    
});

And it worked as expected.

In a real world app I faced this very issue in a more complicated scenario

store.on("articles/get", async (state, articleId) => {   
  store.dispatch("articles/setLoading", true);
  try {
    if (!articleId) {
      const articles = await Article.find();
      await store.dispatch("articles/setArticles", articles);
    } else {
      const articleInStore = state.articles.find(a => a.id === articleId);
      if (articleInStore) {
        store.dispatch("articles/setSelectedArticle", articleInStore);
      } else {
        const article = await Article.findOne(articleId);
        await store.dispatch("articles/setSelectedArticle", article);
      }
    }
  } catch (err) {
    store.dispatch("error");
  }
  store.dispatch("articles/setLoading", false);
};

Basically, when I call articles/get with an argument I first try to look for the article in store and if I don't find one - I make the API call. Quite a common case for a small SPA. And when I find such an article already in store I immediately dispatch an action to set the article. And it fails, if I don't wrap all the async method in setImmediate (or if I don't maniacally add await to every store.dispatch, which is bs).

@Rommero
Copy link
Author
Rommero commented Jul 3, 2019

So far I've tracked down that @Changed event is captured inside the store, but it isn't actually captured inside useStoreon hook (line 34 to be exact return store.on('@changed', function (_, changed) {)

Changing line 48 from
data.dispatch = store.dispatch
to
data.dispatch = (...args) => setImmediate(() => store.dispatch(...args))
seems to be solving the issue. But it doesn't look good to me and just seems that I'm missing something and just jamming setImmediate whereever I want just to make things works.

@ai
Copy link
Member
ai commented Jul 3, 2019

Maybe we need to fix dispatch internals. I will think what I can do here during this and next weeks.

@Rommero
Copy link
Author
Rommero commented Jul 3, 2019

@ai I've tried playing with dispatch internals myself but couldn't find a proper solution there. Probs not a good idea to dig up in storeon's code at 2 am :D
I really appreciate your quick response.

@ai
Copy link
Member
ai commented Jul 6, 2019

In a real world app I faced this very issue in a more complicated scenario

What behavior did you have with this scenario?

it isn't actually captured inside useStoreon hook

Am I right that using store.on('@changed') doesn’t have any problem?

connect("isLoading", ArticleContainer);

Can I as you to quickly check with function component and useStoreon hook without connect?

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

No branches or pull requests

2 participants