Giter Site home page Giter Site logo

Comments (9)

rymohr avatar rymohr commented on July 28, 2024

Just came across this interview that contradicts the diagram above though:

Ian Obermiller

Actually, to clarify, there is no action to fetch data. We don’t have any action type that’s like fetch messages or anything like that. The store takes care of all the fetching for you. It might be doing it from a cache. It might be actually contacting the server. It might be making multiple server calls just to get the data you need, stuff like that.

Andrew Cholakian

What’s the rationale behind that design decision? Was it always that way or is that something you guys learned through trial and error?

Ian Obermiller

For us it was mostly that way mainly because the stores end up being fairly complex. It’s evolved. We started out with basically everything on the server and we would page stuff in, and do sorting and filtering, and have to invalidate some things. We had a lot of caching logic on the client, and the stores in particular took care of that.

Also the stores do the informing when stuff comes back and they know if you were rendering on a specific item, but then someone fetched that item in a list and updated that item, so the store can basically say this item has changed, you can re-render, things like that.

It does kind of conflate the responsibilities there, but it turned out to be very convenient. Really, all stores are is a bag of properties and so adding the fetching logic in there it works really well for us.

From http://ianobermiller.com/blog/2014/09/15/react-and-flux-interview/

from marty.

jhollingworth avatar jhollingworth commented on July 28, 2024

Yet another fuzzy area within the Flux architecture! In general though I agree with Obermiller, Action creators should be for writing only.

Say we have a user store which will load in users on demand:

var UserStore = Marty.createStore({
  getInitialState: function () {
    return {};
  },
  getById: function (id) {
    return this.query(id, function () {
      return this.state[id];
    }, function () {
      return UserAPI.getById(id);
    });
  }
});

Personally I think it makes a lot of sense for the store to be responsible for calling the API directly (which in turn calls an action creator to add the user to the store). Creating an action creator just to call the API seems a little superfluous.

With regards to calling APIs in getInitialState. The entry point into my app used to be littered with calls like UserAPI.getAll(); FooAPI.getAll(); .. but I feel that sort of code should belong with the store (and is in fact its just a special case of the above scenario).

This approach will also help down the line when I start working on supporting isomorphic applications. If you constrain where you get state from the server (i.e. in getInitialState) you can easily introduce alternative sources for that state. This sort of thing becomes a lot hard if you have API calls to get data all over the place

var UserStore = Marty.createStore({
  getInitialState: function (usersFromServer) {
    if (usersFromServer) {
      // this branch would be run on the server
      return usersFromServer;
    } else {
      UserAPI.getUsers();
      return {};
    }
  }
});

from marty.

rymohr avatar rymohr commented on July 28, 2024

My biggest concern with this approach is you end up shoving damn near everything into stores then. Stores become responsible for managing state and process and are tightly coupled to the api. That's a recipe for disaster.

I'm not sure it's a good idea to allow the server/client differences to leak into stores. Instead I'd encapsulate that into some sort of adapter that would be passed to the store by the initializer:

var serverAdapter = {
  getUsers: function() { return usersFromServer; }
};

var clientAdapter = {
  getUsers: function() { return UserAPI.getUsers(); }
};

var UserStore = Marty.createStore({
  getInitialState: function (adapter) {
    return adapter.getUsers();
  }
});

Although the abstraction seems superfluous within the example, within a large app the conditional approach quickly falls apart.

I also think it's best to let the API layer handle caching and default values. That way all stores benefit from it without requiring any form of coordination between stores.

from marty.

jhollingworth avatar jhollingworth commented on July 28, 2024

It's a fair point. Stores now support mixins so you could easily support the adapter pattern:

var UserStore = Marty.createStore({
  mixins: [server ? serverAdapter : clientAdapter],
  getInitialState: function (adapter) {
    return adapter.getUsers();
  }
});

One thing I've been considering is creating some mixins that implement common store patterns. For example

var UsersStore = Marty.createStore({
  mixins: [HttpRestStore({
    identity: "id",
    baseUrl: "http://foo.com/users"
  })]
});

UsersStore.get(123) // => HTTP GET http://foo.com/users/123

What do you think?

from marty.

jhollingworth avatar jhollingworth commented on July 28, 2024

When you say the API handling caching & default values, what are the scenarios you're envisioning?

from marty.

rymohr avatar rymohr commented on July 28, 2024

I like the mixin idea but I'll have to look into that one some more. I'm not familiar with how you've implemented that in Marty but I love the way react handles it within components. Anything that allows stores to be broken up into smaller logical pieces is a plus.

After thinking about it more I take back my comment about the API handling caching / default values. That does feel like a store's responsibility, even if just a thin wrapper around the api.

from marty.

hugooliveirad avatar hugooliveirad commented on July 28, 2024

Just to clarify things up: if I had a UsersStore, and want to implement a search form for users, that search form should call UsersStore.getByQuery('query')?

It is pretty blurry how Flux components should handle fetching.

from marty.

jhollingworth avatar jhollingworth commented on July 28, 2024

Hey, yes thats right. The store should internally check if it has that result cached and if not call the state source (See fetching data)

from marty.

hugooliveirad avatar hugooliveirad commented on July 28, 2024

Thanks! This issue helped me a lot.

from marty.

Related Issues (20)

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.