How to pass a prop to every component in react.js? - javascript

I'm setting up a site using react.js. the client receives a massive json through ajax that is then used to populate all the necessary fields, graphs, etc. Seeing as this json will cover pretty much all the information contained on the site, it has be accesible in almost every single component. Is there a clean way to pass it to every last component (and there are a lot of them)? Passing it the regular way to ~70 components seems dirty and inefficient.

As React's documentation states, you could have components communicate by integrate a global event system, and then subscribe to an application-data event from all your components, in componentDidMount().
This way, each time you will emit the application-data event from within the code responsible for pulling the website data, all components will receive that data. At that point, you can call setState().
Please be careful and unbind the events once a component goes "out of scope", inside componentWillUnmount().
Failing to do so will result in memory leaks, as you will have the event handler dangling, and it will be called each time you pull the website data, even if your Component's instance has been removed from the DOM.
You could also try to make your components pull data by themselves, as sending a huge JSON around, is not the best solution. I mean, each component should use the data it needs, in order to work, not the whole website data. The way I would alter this would be by parsing the JSON object and storing it for reference in a variable, on a scope that is accessible to all components, and use the event system to only notify the components that the data is ready, and each component would go to the global data object and get their data.
Example(pseudo-code):
XHR.getData
XHR.onReadyState => GlobalNameSpace.data = data
EventSystem.PUBLISH('application-data')
// component code
Component {
EventSystem.SUBSCRIBE('application-data') =>
dataNeededForInit = GlobalNameSpace.data.componentXData
}
Reference: https://facebook.github.io/react/tips/communicate-between-components.html

Context might fit the bill. It might not be particularly tidy solution but perhaps that would be a starting point for you.

Related

Standard component interaction mechanisms vs Vuex - how to combine them?

The question is probably more theoretical.
I have little experience with Vue and am trying to figure out where my knowledge gaps are and fill them.
There are standard mechanisms for interaction between components:
from top to bottom - input parameters (props) are passed from parent components to child components
from bottom to top - events are thrown from child to parent
And on the other hand, there is VUEX with its own data storage, which is, roughly speaking, a global variable object with a set of methods for working with it.
Data from this storage is available at any time to any component. And it turns out that the use of Vuex seems to make the standard interaction mechanisms of components completely unnecessary.
Well, perhaps, the generation of events is still needed so that one component can quickly make it clear to the other about the completed action, events, etc.
The question is, does Vuex generally override the standard component interactions?
If it is not, how should it be combined in the right way?
I'll try to answer your question.
Vuex will be very usefull to store data that you'll need in a part of the application or globally, like user data.
If you can simply use $emit or props use it, it will be better and simple to understand the code, because it will be overkill to use the store just for "a prop".
So, you will use Vuex in your component to call an action and fetch / store some data you will need in a another view out of your children/parents context.
I don't know if my explanations are well haha, I tried :)

Passing values between components: Pass References vs Subjects

tl;dr: Why not pass variables by reference between components to have them work on the same data instead of using e.g. BehaviorSubjects?
I'm writing a sort of diary application in Angular 8. I have two components (Navbar and Dashboard) and a service (EntryService).
Navbar lists the entries, Dashboard provides the textarea, EntryService glues them together and communicates with the database.
While debugging the application I stumbled upon a way to communicate between the service and a component that i haven't thought of before.
By accident I passed a variable (entry: Entry) from the Dashboard by reference to the EntryService. The service saved to the database getting a unique ID back and saving this ID into the entry variable. This change immediately reflected to the Dashboard because of the 'passing by reference'.
Until now I was using Subjects to update the components on changes, but passing references around seems to be much simpler, because I want to work on the same data on both components and the service.
I've studied Angular for a while now and not read about this approach, so I'm wondering if it is a bad idea or design and if yes why?
Thanks for your answers!
Passing by reference can be handy. But as a general approach to keep the application components in sync it has some draw backs. With Subjects you can easily investigate in which places of the application the value of the Subject will be changed by checking where the Subject.next() function is being called. When you pass your object by reference to a hundred components/services it will be much more difficult to find out, which of them modify the object and more importantly when, becaue often you want to trigger other changes afterwards. When you subscribe to Subjects, you get notifications about changes and can react to them. Subjects and Subscribers are an example for an Observer/Observable pattern, it allows you to decouple your application logic. And they are much more flexible, for example you can have a Subject which can return the last x number of changes or you can debounce the changes when you track user input, you can apply filters to them etc.

Is it good or bad to share big json data in Angular components?

Considering the code below, is it good to share a big json data as an input to test component or make use of service.
vm.data = [{name: 'John'},{name: 'Steve'},...];
<test-component big-data="{{vm.data}}"></test-component>
Which would be the ideal approach using Angular 1.5 and as well as Angular-2 components?
It seems that you are passing your data through a simple attribute to the component or through #.
In my opinion you should define big-data as binding parameter through <, which allows you to pass angular expressions and then pass the data to the component. It has been introduced exactly in order to avoid the # when you want to avoid objects conversions.
About passing data in general to the component, if your component manipulates that data, sure you can pass it directly all the data as a binding parameter.
There are actually no restrictions about that.
Then if it's better to use a shared service between the component and the app in order to get the data, this is usually depending on the specific use case.
For example, if your component works always with the same type of data, retrieved by always the same request, maybe you can get the data directly inside the component through an embedded service.
But actually the goal of components is to have a reusable code, so usually the approach you are having is a good choice, because your component could be reused providing any kind of data.
Actually the data is out-of-the-box and it's working doesn't depend on the particular data.
I hope this helps.

Flux: should not-top-level views be "dump" (do not fetch data from stores)

Maybe at official flux website I saw a video were mentor said something like:
Only top-level React views should know about stores. All not top level
views should be dump and receive all information as properties.
Question: Is that right? Your argumentation, please
BUT, suppose you have some small React view Button.react that's reused on multiple pages. And suppose Button.react must know about some store data. If we won't fetch all data directly from the Button.react, we get a duplication of code at each top-level component which reuse Button.react. Is that ok for you?
I hope I am understanding your question.
One of the characteristics of React is its one-way data flow. Each component can be used by another component, just like one function can call another function. Just like a function, a React component should typically be able to get all the info it needs to do work (render itself) from the arguments passed into it. This is the function of props in React. When using Flux, sometimes the React Components, which are typically near the top of the view hierarchy, that actually fetch the data from the stores to pass down thru the application are called Controller-Views.
It is not an enforceable rule that every component doesn't become a Controller-View, getting its own state directly from a store, but it is a general practice for good reason. consider the two functions:
function renderToggleButton( isSelected ){
//... render the button
}
vs
function renderToggleButton(){
var isSelected = StateStore.getButtonSelectedState( id );
//... render the button
}
I think you will agree that the second function is more complicated and difficult to test. It has to know from where it is getting it's initial conditions. It also has to know how to identify itself in the context of the application. These are two things the function should not have to know.
Now imagine an application full of functions like this. If one function is misbehaving, it becomes very difficult to trace its inputs; to test it under controlled conditions. I hope that clarifies the guidance given for passing data thru the application as props.

Flux calling actions with arguments managed in store

Say I have an action someAction(params) that takes params which is managed in a store paramsStore:
paramsStore.listen(function(params) {
someAction(params)
})
It seems that I can't just call this in my view because apparently this goes against the Flux way of doing things (actions shouldn't be called within store listeners).
The reason I have someAction inside the store listener, is because I want it to be called every time the paramsStore is modified. How can I achieved this without resorting to the 'unpattern' of calling actions within stores listener?
The right "flux way" of doing it would be to call the someAction(params) wherever information is dispatched to paramsStore.
Understanding what someAction does will give more clarity. Does it really need to be an action? If you're just doing some manipulation in the store data, you could have it as a local method in the paramStore.
While I am new to flux as well I could offer a suggestion. State that is needed to determine the outcome of an action that is held by Store A could be attached to a get method. This state can be retrieved by a View with a getter. When the action is called this state can be sent as a parameter. If something needs to be async it can now be done here (ajax call or something else) based on what the state is. Either the result of this or a promise object can then be used to trigger an action which is passed to the dispatcher. The dispatcher sends the result or promise to the store. The store then updates its state and the process repeats as necessary (when initial action is triggered).
I think a little more detail of what exactly you need would help actually. I do believe listening for for an action and triggering another action inside the store doesn't coincide with flux. I do think there is likely a way to accomplish the actual result you want using flux but without more detail this is the best I could come up with. Also, in reality you can implement anything you want. Flux is just a model and by extension a self imposed constraint to help with structure.
If you are using Flux as is, you could refer to the original image of the whole architecture at https://github.com/facebook/flux.
As you can see not only views could create actions. There are also Web API Utils which could create ones. Generally speaking not only API utils can do this. It's totally okey to create actions in order to start some behaviour according to outside world, some services or something else.
But in your case you are trying to create an action on some store update listener. As far as I can understand this would result in some changes in one or few other stores. In this case you probably don't need to create an action in the listener, but rather create some relations between your stores with waitFor API. Here is a link with detailed information: http://facebook.github.io/flux/docs/todo-list.html#adding-dependency-management-to-the-dispatcher.

Categories

Resources