Comments (12)
I suppose I could make a mixin to eliminate some of the boilerplate, but this doesn't really solve the underlying problem: now, instead of storing state just in one place or another (in the component or store state), it's effectively stored in two places, which makes it a pretty terrible state mess.
from flux.
Digging a little deeper – sometimes parts of component state is not mirrored in stores – in the chat app, the message composer stores the message while it's being composed in local state, but when it's saved, it gets moved into a store. Maybe I'm not seeing something here – but it feels very inconsistent to me, and again, spreading state out over more places than necessary. Thoughts?
from flux.
Hi Dmitri,
We call them controller-views instead of ViewControllers because they are actual views, and not exactly controllers in the sense of MVC. They do pull data from the stores and pass that data to their children, however, and this is somewhat controller-like. Hence the name controller-view: a view that has controller-like functionality. If you compare this with ViewControllers in iOS, for example, you'll see that most people use that term to mean actual controllers that manage views, and do a whole lot more than what we are talking about here.
The use of setState() is a convention of React. You can certainly use forceUpdate() instead, but having the handle to this.state can be convenient. We are not really managing state in these controller-views. It's simply a convenient way to respond to the 'change' event and to get the data to the render method, allowing the render method to remain dedicated to rendering logic, instead of putting data fetching in there too. As long as you're not actually trying to manage state in the controller-view, there is nothing wrong with using this.state in this way. All the children below this controller-view will simply take the data in as props, and remain stateless.
When an individual component needs to manage it's own state (such as an input element, as you have noted) we do use this.state to do this. This is the one place in a Flux + React app where you do store state in a component that would otherwise be stateless. A significant difference here is that only this one component -- none of its children -- no other components -- need a reference to the component's state. Shared state should always be in the stores and pass through the component hierarchy as props. For more info on why input elements need to manage their own state, please see:
http://facebook.github.io/react/docs/interactivity-and-dynamic-uis.html#what-components-should-have-state
and
http://facebook.github.io/react/docs/forms.html
I hope that helps!
from flux.
Yeah, the name makes total sense... I think I must have just forgotten – at least I got that the name had "controller" and "view" in it :-)
Very interesting on the distinction between shared state and individual state. Makes total sense. Maybe this is a silly question, but would it make sense for a component which manages its own state pass that state down to other components through their props, and listen via some kind of change listeners? In that case, why not have controller-views encapsulate the state entirely, without using stores?
Also interesting thought on using this.state as an effective shortcut to the store. I guess another part of my concern is mixing "store-state" with "component-state" in some components gets messy as well. I've managed this by having controller-views hold all their state in the store, even when it's not necessarily shared state. Does this make sense to do?
from flux.
Thanks for the answer @fisherwebdev
@dmitrig01 If you need to share state between react components flux recommends using stores, I see controller-views as views that layout other views and pass store data into them. Not as places to try and keep consistent models as you will be mingling concerns (the view and the domain model) if you were to do that.
State in stores doesn't have to be shared so I don't see an issue with storing everything in stores.
Your problem might be that your app isn't quite complex enough to require using flux, flux is something I would use for medium to high complexity applications/components.
from flux.
@fisherwebdev still curious on the best practice here – not sure about the best practice in terms of mixing "store-state" with individual/component-state in the component's state variable. Isn't it a little messy to do?
As a concrete example, I have a controller-view which has three pie charts which have the same keys but different values. When you hover over a slice on one, the same highlights on all three. The data contained by the charts would be considered "shared state", and resides in the store, but hover data seems to be state local to the controller-view. However, the component's state variable now contains aliased state from the store as well as actual/local state, which feels very messy. Does this make sense?
from flux.
Hover state does not seem local to the controller-view, that should be state that is local to the child view components, you hover over them not the view controller. The view controller just passes what is hover over into the child views when it's notified of a change by the store it listens to.
You shouldn't store hover state in the child views either then as they should have that value passed in to them from their parent view controller, all they do is call action creators which will eventually be handled by the store which then notifies the view controller which then...
from flux.
Interesting, this is what I got from what you were saying:
- Store the hovered state in a store
- Pie charts have an onHover callback
- The parent controller-view attaches an onHover function to its child pie charts that set data in the store (well, fires an action that sets data, but w/e)
- Have the parent controller-view pass in the store data to the when the store changes
Is that fair, or are you thinking something more along the lines of the pie chart components are actually their own controller-views? That feels really ugly to me.
In this instance, it seems somewhat pointless to store hover data in the store, as it's not shared state – it's only used in one instance of component, the controller-view
from flux.
@dmitrig01 Very sorry to have closed this on you. Please close when you feel you are understanding the Flux way of handling this.
We want to get rid of as much state from our React components as possible, and to move that state into the stores. So every time you find yourself keeping state in your components, ask yourself: "Can I move this state into the stores?" After thinking about it a bit, you'll find that this is possible, and it actually cleans up your code quite a bit. In your scenario, the hover state would be kept in the store as well. This might be something like the ChartStore's private _hightlightedPieSliceID variable.
The only exception to this rule is state that is 100% internal to the component, and even this is often something that can be put in stores. As I've said above, text input components are an example of this kind of component.
Controller-views are slightly different, however. The state they contain is often, as you say, a mirror of the stores' state. It also can be tailored to their specific needs, by providing more specific getter methods in the stores.
So in your scenario, I'm assuming you have something like this:
<PieChartControllerView>
<PieChart />
<PieChart />
<PieChart />
</PieChartControllerView>
You could either get the entire state of the ChartStore, including the _highlightedPieSliceID (which can be null), or you could more specifically invoke ChartStore.getHightlightedPieSliceID().
Each PieChart would then receive the id as props, and know what to do with it.
from flux.
Is that fair, or are you thinking something more along the lines of the pie chart components are actually their own controller-views? That feels really ugly to me.
Yes, it sounds like you understand it correctly. No, they should not be their own controller-views.
In this instance, it seems somewhat pointless to store hover data in the store, as it's not shared state – it's only used in one instance of component, the controller-view
It's not pointless. It maintains the proper data flow, and as soon as you want to do something else with that hover state, like display related information in a table off to the side in a different column, you are looking at a significant refactoring. If you stick with the Flux pattern, you will have an easier time down the road. You will know where all the state is being maintained, how it gets updated, etc. Six months from now you will be able to open this app up again and know where everything lives. Putting the state in React components makes them less reusable, harder to reason about, more tightly coupled to each other and their specific context.
And it is in fact shared state -- each PieChart needs to know the currently hovered slice.
from flux.
Since we haven't continued this in a while, I'm assuming we're okay to close this one.
from flux.
yes – thanks
from flux.
Related Issues (20)
- Cannot dispatch in the middle of a dispatch. HOT 1
- New Flux store instance created upon second component referencing store HOT 7
- Flux Utils + Hooks HOT 6
- TypeError: Class constructor App cannot be invoked without 'new' HOT 1
- Using version of fbjs that depends on unsupported core-js module HOT 2
- Please update the following components: FluxContainer(containerClass) React 16.10.2 HOT 5
- how do we differ from Architecture and pattern? HOT 1
- Is this code a good way to update react component from dispatch in OOP class object? HOT 2
- Flux container breaks class methods defined with class properties syntax HOT 1
- Container create context issues after Babel 7.9.x update. HOT 5
- CVE-2020-15168 found in [email protected] HOT 13
- CVE-2020-7733 vulnerability by linking to an older fbjs version HOT 2
- Is fbemitter project discontinued? Is flux? HOT 1
- Add React 17 support
- NPM reports flux vulnerabilities HOT 3
- CVE-2021-27292: ua-parser-js needs to upgrade to 0.7.24 HOT 4
- mock flux store - react test HOT 2
- Will there be a Chinese version? HOT 1
- Video goes off screen and does not fit neatly HOT 1
- Add react-18 as peer dependency. HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from flux.