Passing down props in a React library invisible to the app using the library - reactjs

I am developing an open source library to use the Ionic framework with React (it normally works with Angular): https://github.com/pors/reactionic/
This React-Ionic library can be used by developers to create mobile apps. These apps will have their own way to keep state in their app, either by passing down props through composition, or using Flux/Redux, etc.
The React-Ionic library also needs to keep state for a number of things. For example, the "Body" component that wraps all contents needs to know if the content contains "Tabs". So the "Tabs" component needs to be able to change the state in a higher-up component.
I currently use composition to do this, but this has the disadvantage that the app developer needs to pass on props that are specific to the React-Ionic library. I want these props to be invisible for the developer.
What is the "React way" of solving this? I can think of two things, please let me know what the best solution is:
Use context.
Use Flex/Redux just for the library. Is this possible? Won't it interfere with the "state management" used by the app?
Otherwise?
I have added an image that hopefully clarifies what I try to accomplish:
So I want to pass state information down from the IonBody component to the IonTabs component, without the "App component" having to pass props down. And similarly, the IonTabs component should be able to call an IonBody function.
Thanks!

1) If you want to pass props down so they "fall through" to a child component, you can use the JSX spread operator, which will merge in old props:
<Component {...this.props} more="values" />
2) Context is an experimental feature and shouldn't be used unless in a very specific few cases; it essentially lets you create a "falling leaf" outside the state tree you create w/ props. This can lead to very unexpected results since it is generally outside the React/Flux paradigms. There are a few use cases for it, but they're generally only as last-resorts or only with very specific rationale
3) With one-way data flow, you generally want to use something like Flux/Redux for your state management. Child components don't get to really know about their parents, and vice versa. They communicate via props (and only top-down, really), so actions need to go "back to the top" of the state tree and propagate down from there.
As a last note, I wonder if you might consider React-native over React-ionic. It's going places IMO and is probably the ideal choice for taking a React app native. Just a thought :)

Related

What "data" should you pass with React context

The React doc's say that context is for passing data around without prop drilling
I get that usually that "data" will be some kind of state.
What other kind of data might you want to use context for?
Specifically, we have a service layer object that has a bunch of methods to interact with APIs and external libraries. Is there any benefit of wrapping these objects in context?
They seem to work fine just accessing them like any regular import but colleagues are saying they should be wrapped in context.
Context is useful to share data that won't often change across component avoiding props drilling.
For instance, let's say you have a modal component and you want to be able to control the open state of your modal in many components, you may want to provide a context for your modal component (that what react-modal)
For your question about benefits of wrapping services in contexts there is no real answer, it depend of your project structure and your state management,
if you're request consume context based data (token, cache or ids) why not but if you use other state management system and your services relies on it, I would say there is no reason to wrap your services in context.

how to find parent component of props

how does one track the source of a component’s props that were set in another component?
I am working with only two or sometimes three components, but imagining a large application with many components, I am not sure how I would find the parent component where the props were defined and passed into the child component (assuming I am viewing the child component).
I would appreciate your help.
To track the origin of props I suggest using browser extension: React Developer Tools. It offers a great interface to track, see and manipulate props from inside your developer tools.
What you're describing is known as "Prop Drilling" or passing down props through multiple levels of components. To avoid this, there are two options I would suggest. React's Context api or Redux. Personally I like both but I would lean more towards context as it requires less code but some of the features of Redux-Saga's middleware makes it easier to respond to multiple events.

React components with shared state that are far away

I am new to React so please excuse me if this is a noob question but I really could not find the answer in the DOCs or elsewhere.
Let's say I have two buttons with a counter that share the state but are far away from each other in terms of the placement in the UI.
The documentation says the common owner component for both buttons should own the state. It makes sense if the components are next to each other like in the example but what if my buttons are each part of a different UI group and are far away in terms of nesting? My state holder would be the root of the document and I would have to pass a handler function down through many layers. And what if I need to add new component somewhere else that also needs to know the state? Would I have to modify all the parent components in the way to pass the state down? That is tremendously impractical.
Without React I would have some global Subscribe/Publish pattern like jQuery Observer and all UI elements could subscribe/publish to it regardless of their nesting position.
How does React solve this?
Related question: If I need to load/save the state to DB, how do I pass a reference of the controller (or Whatever) to each React component that stores the state?
1 for global state you may use REDUX
Redux is a predictable state container for JavaScript apps
for connect/subscribe component with that state ,you should use react-redux
If components are far away in terms of nesting, you may connect/subscribe them to redux store, and take only neccessary part of state. They will update if only neccessary part is changed.
article that explains how you can do your case
to learn how to use redux you can watch this videos from creator of redux (Dan Abramov)
1.getting-started-with-redux
2.building-react-applications-with-idiomatic-redux
3.I definitely recommend to you discordapp rectiflux channel. because you allways can ask any question online.(there you can find contributors of that tools)
2 alternative way that less verbose then redux is MobX
MobX is a battle tested library that makes state management simple and scalable by transparently applying functional reactive programming (TFRP). The philosophy behind MobX is very simple:
Anything that can be derived from the application state, should be derived. Automatically.
I suggest to look at the Flux stores. In short, stores are like model in your application. You can listen to change (subscribe) and also modify their properties (publish). You can see how it was done in example app.
A better option is to go with Redux.
Redux is enabling use cases like yours in a way simpler fashion :)
It will help you with all the state and make your life much easier.
Some good resources for learning:
The Redux Website
Video courses from Dan Abramov, the creator [Free]
Awesome course on Udemy [Not free]
Building Applications with React and Redux in ES6
And finally take a look at this youtube series [Free]
Managing state in the middle layers of your app should be avoided where possible. This data belongs in a store, which holds the global state of the app. Then each component accesses the state via its props.
The naïve approach to get the data down to the component is to pass the store through all the layers of your app "manually", i.e. through props.
Smarter alternatives exist, which use connected components, that access the global state through the context (as opposed to the props). Typically, the presentational component (your button component) is wrapped in a container component that handles this connection to the store, then passes the data in via props.
There are numerous frameworks that facilitate this process, links to which are already provided in the other answers.
If you are trying to share simple states, try this ( I am the author): react-provide-state
Otherwise I will recommend Redux. It has become the most popular tool for managing application states.
In the applications being working on, we use Redux to manage the main application states and almost all other states. But we use 'react-provide-state' for simple, UI only states like Modal, Checkbox states.

Where should be the line to separate stateful and stateless component in React?

React encourages the use of stateless components as much as possible and have a stateful parent component managing them.
I understand that this can make the stateless components more reusable, and easy to manage.
However, to the extreme, we can always put the state at the top level component, like App.js, and pass down information and callbacks through a long props chain. And if using Flux, the actions can always be dispatched in it too (executed through callbacks).
So I'm wondering what's line to separate stateful and stateless components? And if using Flux, where should the Actions to be dispatched?
--- Add an example ---
Say I have a google docs like web app that have a tool bar and displayed content. I imagine we will have the component structure.
<App>
<Toolbar />
<Content />
</App>
The tool bar has buttons that will affect the display content, say the bold text button.
So should the App pass down onButtonPressed callback props to Toolbar and dispatch Actions in itself, or should let the Toolbar to do it itself?
Should the App pass down contentString props to Content, or let Content itself listen to Store changes?
Thanks!
From my point of view, a simple application could use the pattern of Flux in that way :
Children emit actions.
The application listens to stores and propagates processed data to his children.
With that approach, you have the stateless component, but with a good code organisation without the callback props. But both of your propositions are also correct, it's a decision that you make regarding the size and needs of your application.
If the component that you build will be used outside of your application, don't use flux as much as possible and let the developer choose the wanted approach for his needs.
It's a good question, and it is being solved differently even between different Flux implementations.
I prefer having my state in one high-level component, that sees the "big picrure", and propagate data using props to all the low-level ones. In a good React app, most of the components shouldn't "care" where the data is coming from.
Having a one good structured model instead of several fragmented ones also proves itself to be beneficial so far. (by the way, that can be achieved even using several stores, the high-level component could listen to all of them, and virtually "hold" this big model).
Regarding actions - I prefer having all my "dumb" visualization/ui/display components work with callback props. That way it is easier to re-use them, and it is a good separation of concerns.
In richer components that hold a bit of business logic, I call Reflux actions directly. Usually those are also container components themselves to aforementioned "dumb" ui controllers.
So bottom line - data should flow from as high as possible, actions can be fired from lower components, but always check whether you can achieve the same result with callback props.
To your question - the Toolbar is a complex enough component to have ToolbarActions of its own and call them directly. But the Content component should definitely get its data from above. It's also easier to reason the data flow that way, when the app gets complicated.
Hope that helps. The whole Flux thing is still an art in progress...

Issue with UI event when rendering component inside a web component shadow DOM

I'm facing some issues when rendering a React component into the shadow DOM of a webcomponent.
I wrote a small piece of code to turn a React component into a webcomponent, but I want to render the
React component inside the shadow DOM of the webcomponent. But in that case, it seems that React is not able to catch UI events (click, keyPress, etc ...) anymore.
Let's take an example, let say that I have a first webcomponent <awesome-timer /> that render the React component inside the webcomponent node, and another webcomponent <less-awesome-timer /> that render the React component inside the shadow DOM of the webcomponent.
Both webcomponents use the same React component. However the one rendered inside the shadow DOM does not work, because click events on the button of the timer component does not trigger the bound function.
I guess React is not designed to handle such case, but I'd love to get more details about it.
The code of the example is available here : https://gist.github.com/mathieuancelin/cca14d31184bf4468bc1
Does anyone have an idea about it ?
I know this is kinda late but, I believe your issue when you pass any attributes to a web component they instantly become strings Because that's all you can pass to a web component. Now of course you can convert or cast them back to there original data type, except functions because once stringified they loose there scoping, lexical and all.
Now to your main question, you are were trying to pass you child element through the Main web components slot. Now you have to remember that once you pass anything to a web component you now have to use the webs components methods and return types to manage whatever you pass. So yes passing react into a web component will not work they you expect.
You will need to go back to whatever tool you use to build your web component and deal with the slot logic there. Since this is a very old post as are web components. You might not have had access to the modern web component build tool's we have today. I found Stenicl allows you to build and manage your web components in Typescript.
A good option is to change your pattern a little bit and just return web components from your react app.
Or you can use another really cool to call Lit-HTML or Lit-element. I believe they may have combined there core libraries. Anyway these tool will allow you to combine Reactjs and web components where lit-html gives you access to methods simial to Reactjs's life cycle methods. Anyway some good stuff to check out if your stuck at this point.

Resources