Different actions for common components in FluxJS - javascript

In my flux application, I have a DropDown React component that renders itself with an array of Key Value Pairs.
I'd like to have two different drop downs, one with Country Data, and another with City Data.
In the Flux pattern, each dropdown would have a Selection Action that contains a payload of the selected value, which a corresponding store would use to update it's state.
How do I specify which dropdown Selection action belongs to which store?
I can create a wrapper component that is specific to each need i.e. CountryDropDown and CityDropDown, and have each create their own specific action CountrySelected and CitySelected but is that the idiomatic approach? If it is, how do I wire up the underlying DropDown component so that it's onChange handler fires the parent's action?

Actions should not belong exclusively to one store or another. This is very much like creating a setter method in the store, which is antithetical to Flux.
One of the central ideas behind Flux is that all stores are informed by all actions. The dispatcher is the mechanism by which actions are distributed to all the stores. This keeps the flow of data open to changing needs.
There are probably a few different solutions to your problem.
I would consider adding a selectedType field to the action that is either 'city' or 'country' (or you could use constants instead of strings). You could pass this value into the React component as a prop, if you are trying to keep it abstracted.
Likewise, if you would rather have completely flexible control over the behavior of the child, and you want to define that in the parent (your final question above), you can pass a callback to the child component as a prop.
You could have separate actions dedicated to each type, as you described, but that seems like duplicating code to me.

Related

Update UI on Data change

(I mostly work with Vue.js so many examples will relate to it)
I am learning to build web apps and the most time-consuming thing is the synchronization of the UI components and the data that they should represent, that is, coherence between what is shown to the user and what is stored in memory (locally).
For instance, suppose I have the following component tree:
<body>
<form/>
<task-bar/>
<component-1>
<component-2>
</body>
Here the parent component is body, and it has four childs, namely form, task-bar, component-1 and component-2.
We have a list of objects, for example:
[
{
id: 1,
title: "X"
},
{
id: 2,
title: "Y"
}
]
Taskbar lists the component title.
Component-1 shows the object selected in Component-2 via a radio button.
Now, in form I want to add an object to the list or edit/delete the selected component in Component-2.
In Vue.js I would pass the list from parent body to its child components, however, parent and siblings are not reactive by default to the data of child and siblings. Therefore a change on the list by a sibling creates an incoherent state between all components.
I read two ways to solve it, first is using events, child does something and notifies (This is what I used to do back in Java Swing, an observer pattern), this however turn to be extremely cumbersome after some events, moreover, its hard to debug and you might repeat events code in different components.
The second way is using a global state, such as Flux pattern implemented in Vuex. This however couples all components to the Vuex of a the specific project and makes it less portable.
My question is, are these the two unique ways to do things? Am I doing it the wrong way?
You could also do one of the following:
use a variable like it was a global state. You have an example of this in Vue's doc: https://v2.vuejs.org/v2/guide/state-management.html
in your component, use $parent.doSomething(), where doSomething() is a method of your parent component.
But personally, I like vuex :)

Parent component triggering action in multiple child components - preferred way in React (hooks)

I have a parent component which has three other components, A B and C.
Each of these components has its own set of fields that can be saved. These are different object types. And now, when user clicks "Save", I want to trigger a save action in each of these components. Each of them has its own error handling, messaging etc.
How to handle it? At the moment I'm just using references, but according to this post (Call child method from parent) this is not encouraged. How to implement it in "React" way of thinking?

React why pass down functions to components anyway?

I am just wondering, why do we define every component function in one place (e.g index.js) and then pass those functions down the components? Does that make any sense?
E.g I want to define a click handler for a list button component, and another click handler for some forms button component, why would I define them all in one place? Isn't the divide-and-conquer approach better?
I mean, why would I not just define my click handlers in the components themselves, where they belong? beside the fact, that everything in one place gets messy and hard to upkeep...
I want to define a click handler for a list button component, and another click handler for some forms button component, why would I define them all in one place?
Because of the nature of the unidirectional data flow that React employs, state flows down the tree and events (i.e. changes) are passed back up via handlers such as the ones you mention. Components deep down in the tree can (or rather, should) only propagate changes back up via clickHandlers and the like.
The reason that handlers are often defined together in only a few places is because those places typically represent points where common state is shared, so the events that update that state need to be handled there.

Flux + React: when to keep state of visual components at store

Sometimes it's not obvious: where I should keep state of React view, i.e. active tab, selected option, toggler value, is input validated flag?
Actually there are two options:
Throw an action and keep that data in store
Keep that data as view's state
Which of them is better? Are stores intended only for data from server?
My considerations:
That's bad to keep that data in store, because that lead to chain of actions. Example: you need to download data on tab selection - so you trigger an action NEW_TAB_SELECTED and from the store which handle it trigger a new action DOWLOAD_TAB_DATA.
Keeping data in view allow to avoid the first action (NEW_TAB_SELECTED) and avoid action chains. But how to keep selected tab if I want to leave this view?
Things that should be kept in the component's state are things which only affect that component.
So, for example, if you have a component which opens to reveal more content then the isOpen flag can be kept in state because it's internal to the component.
If the information is not part of the component (such as the text of a message and whether the message has been read) then it should be kept in a store and circulated through the app as needed.
Changing the state of a component will cause it to redraw, so try to keep state to the minimal possible representation of its state, and only store those properties in this.state.
Therefore, from what I can gather from your question, I'd suggest keeping active tab, selected option, toggler value and whether the input is validated in this.state. They are all properties of the component but don't affect any other components. I'd keep the data which populates the views in a store. I'd keep the flags which indicate the state of the view in this.state.
Hope that helps.

How to update two different React component instances that represent the same data?

Say I've defined a <Tag> component that has two props: id and name. My application renders this component in two different places, so I have a <Tag> component whose id is 1 appearing twice, but whose owners are different. One tag is owned by an <Entries> component, and the other is owned by a <Tags> component.
When a <Tag> is clicked, I want to change its state, and I want all other <Tag> components with the same id to also change their state so that they match. What's the best way to do this? Should all <Tags> have the same root component? I don't like that idea, because I feel like it's a brittle solution.
I think you have two options to go:
1- React way
You should keep the state in a common owner component of <Tags> and <Entries>.
You should pass a change handler from the state owner component to the <Tag> component
When the tag changes the state owner will update <Tag>s in both <Tags> and <Entries>
Reading this should give you a lot of insight:
http://facebook.github.io/react/docs/thinking-in-react.html
2- Pure Flux way
If your application is a little more complex than what you have told you can go with flux architecture.
To do this you should have actions,dispatchers and stores implemented in your application.
When a <Tag> is changed you call an action, which in turn calls a dispatcher, which is in turn listened by stores, which in turn emits a change event to components. Then all the components updates themselves with the new state.
You can find about flux here:
http://facebook.github.io/flux/docs/overview.html
id's should generally be unique within an html document.
The best solution would be to change your id's to classes.

Categories

Resources