ReactJS component communication - javascript

I am wondering what is the recommended way to communicate between ReactJS components. I took a look at a related question. However, I did not find the answer sufficient. The key approaches seem to be the following:
Assume that only childs / parents communicate.
Communication from parent to child is realized by setting props, the reverse is realized by passing a callback as a prop.
This has the following disadvantages:
Since siblings can't communicate directly, all state which has to be passed back and forth between siblings has to be stored in their common parent. This means that the parent has a lot of state which it doesn't really need.
Passing callback is rather inelegant.
What I would like to do is to add to components methods / members in order to establish communication. I am thinking along the lines of RxJS. This would mean the following:
I accept that communication is out of the scope of functionality handled by ReactJS. This seems to be the case anyhow.
The members of classes need to be persistent. For example, a parent component should not create a new <Child /> during each call to its render function since in this case all the subscriptions would have to be reestablished. Instead the constructor would have to create a this.child = <Child /> object and in the render call render {this.child} instead.
My question is: Is component communication somehow handled by ReactJS or is this something that should be taken care of by the developer in some other way?
In the first case: Is there a scalable and elegant way that communication between components can be realized in ReactJS? Is the rationale of the developers of ReactJS is done in the way described above or is there something I am missing?
In the second case: How should the components communicate instead?

Well there are two established way in React to communicate between components.
Observable architechture: Mobx
Flux like architechture: Redux
Note: Look at mobx if you are not sure what to start with :)

Related

Is using a React's Context for form with steps a good idea in general?

If I have a form with a couple of steps, should I use Context API or state inside of the parent component?
It's a good question. It depends on your purposes. So, for state management you can use context/ref/state/or library based on FLAX pattern.
I prefer to use context in a lot of situations. If you want to avoid props drilling then the best solution is to use context/ref, but if you have to rerender all your steps then context isn't suitable for you.
Here you can understand all benefits of using context
https://daveceddia.com/context-api-vs-redux/
The only difference between Context API vs "state in the parent component" is how many levels you have to pass down props (the Provider in context is "state in an ancestor component" rather than a parent component).
So it depends on your component structure. If you have to pass down a callback prop more than one level, I'd go with context.
EDIT: With reference to a comment - your own personal preference comes in play with how far you are willing to prop drill for simple state vs context. I don't like doing it more than one level. In my opinion (that's a big IMO), it mixes the concerns of a component - you'll end up making a component accept props for the sole purpose of passing them on to child components.
That depends a lot, but I honestly prefer in this use case to use it as state in the parent.
Context API, as it says in documentation, was designed for "global" share of data between a tree of react components. I don't think you should create context just to avoid passing props through components. I'd prefer to rethink component structure to make it possible to do less props drilling.
Those two blogs from Kent C. Dodds helped me a lot:
How to use React Context effectively
How to optimize your context value

React architectural problem - Best way of having a single global application state, updating child components when changed

I'm quite new to React, and I'm making a single page application with React.
So far, I've build the application with components and child components, having their own local state, however the child components doesn't really interact with one another, which is what I want them to, basically, with the least amount of boiler plate code...
The problem I'm facing, is that a change in some child component, should be able to update the state of another child component, somewhere else in the component tree.
A selection in one child component should also be able to trigger a function in another component updating it with data and so on.
I've considered having just one global application state, that all components can call and update when something in them changes, and this one application state will then update other components in the tree. Kinda like having a single "controller" with it's own state, that all components "views" can call, and which updates the states of other components as needed. (I'm used to WPF and MVC style of GUI programming).
What I've considered:
One could try to implement this with callback functions defined in the top of the hierarchy, to be sent down through the hierarchy and called from a child component when it changes.
This method however results in a LOT of boilerplate code that just passes functions to their child components. It feels wrong and hard to maintain...
To avoid all this passing around and boilerplate code, I've tried using a React Context, however this is not working as well as I hoped. I can only access the context from within the render function and from lifecycle functions, and sadly I often get complicated errors that are hard to understand. It seems like I'm exploiting React Context to do something you shouldn't use it for...
I've considered using a singleton pattern in JavaScript, however then that singleton needs to have a reference to the root component, and query for the component it needs to change... This seems like kind of a hack, and may not be that pretty, but idk.
I'm considering trying out React Redux however it seems to work in many ways similar to React Context (I'll be honest, I haven't read much into it yet).
What I need:
I need to ask someone with greater React experience than me: How do you keep a global application state, and update child components based on changes to the global application state? Also: Am I thinking about this all wrong? Am I trying to do something in a non-react way, failing to see how I should do it in React?
You can happily go with Redux or MobX, they're fine.
I suggest Taming The State from Robin Wieruch: https://roadtoreact.com/course-details?courseId=TAMING_THE_STATE
There are the book and the course. He shows different ways of handling React state.
Redux was created specifically for the problem yo stated.
Reacts follows a top-down down-top unidirectional flow in essence. Context API is useful in simple use cases but would fail horribly in a large scale application where you'd be creating consumers everywhere.
I'd suggest investing some time in Redux so that will save your precious time in long run.
There's a reason all big three frameworks require a state management library to be useful for large scale complex apps. (Angular has NgRx and Vue has Vuex).

What is the best approch to send data to its descendant in REACT

FOr example I have one parent component ( i'll call it animal)
and several child components (dog, cat, horse) and child's child components (Collie, English Foxhound, Fox Terrier, German Shepherd Dog). If i wanna send a function from animal to Collie, i have to send this function to Dog component and from Dog to Collie and only after 2 props i will be able to use this function in Collie component. Is there any better approch to send a function from animal directly to Collie ?
As mentioned by others on top the new Context API that was introduced in the new versions of react maybe different in react versions and still not recommended for just avoid passing props a fewer levels down in the component tree.
The component composition is a better option if you don't want to use redux which maybe complex for less usage like this example.
https://reactjs.org/docs/context.html#before-you-use-context
You basically create your parent component in this case <Animal/> to expected children nodes, <Dog />as well to expect children then you can later on pass it <Collie /> with the props.
Use the Context API.
Read more at the official docs : https://reactjs.org/docs/context.html
Basically, you define a context value and pass it with a Provider, which can be accessed by any node within the child tree.
Do note that the Context API is different for different versions of React and may change in future. You may also use Redux and react-redux for state management which would be internally using the context api.
You can use React Context API which is now official. More information as to how to use this can be found here - https://hackernoon.com/how-to-use-the-new-react-context-api-fce011e7d87
I would recommend to take a look at React "Component Composition" pattern (docs: https://reactjs.org/docs/composition-vs-inheritance.html). It is pretty straightforward and doesn't have a reusability issue that sometimes might occur in with React Context.
Ta-ta

ReactJS - Global state outside of components

I've been reading and watching videos on Redux and seeing a lot of debate about managing state in components or with Redux. What I'm not seeing is anything about managing state completely outside of components with standard global variables.
For example, I could set a global state variable like this:
let state = {
player: {
username: "BillyBob",
score: 100
}
}
Then in a React component, I could have something like this:
incrementScore() {
state.player.score += 1
props.update()
}
Then in App.js, I could have this:
update() {
this.forceUpdate()
}
I realize that I'd still have to pass the update function down through the tree, but I'd at least be able to set functions at the component level and not have to worry about passing multiple pieces of state and functions to child components.
I'm new to React, but the only downside I can think of is not being able to require propTypes. Is there anything else I'm missing?
EDIT: Per request that I clarify the question, are there any major downsides to the implementation above that I should be considering that would affect even a relatively simple app?
If you look at the implementation of redux or some other state management library out there (for example mobx or mobx-state-tree), basically all of them maintain the state outside of the component as a standalone object.
However, to detect changes and trigger re-render efficiently, they implement a HOC, it's connect in redux and inject in mobx, what the HOC (higher order component) does is to wrap your component inside another component that have access to the global state, and pass the part of the state require by your component via its props. This way, the component only re-render when the data required by it changes.
Compared with these popular library approach, there are couple problems with your proposed solution.
The first is using forceUpdate, basically, the last thing you might want to do is to call forceUpdate on the root node of your app, think about scenario when someone type in an input and the whole app re-render every single keystroke.
The second will be passing an update function down to multiple level of children, it will be fine if you have only 1 or 2 nested component, but will be a big problem one your app grows. As your app grows and your state become more complex, it might not be the best idea to have a single update function to control the whole state object.
React exists to solve the problem of creating a user interface that is composed of several indepentent pieces that can be developed in parallel and can seamlessly interact with each other.
If you are going to use global namespace to define your state then you are going to bypass most of the key features of React such as:
1. Lifecycle methods
2. Virtual DOM
3. Controlled Components
4. Rendering Optimizations
In a nutshell, you are going to end up with all the overhead costs of running React while missing out on its benefits.
The 'catch' in learning a new framework or paradigm is to understand how to define the problem in such a way that it leads to path of least resistance. This can be achieved by introducing a constraint and then solving the problem within that constraint.
By favoring vanilla JavaScript for state management, you are not giving React and Redux a fair chance.
I've created a library exactly for this use case :)
Simple 💪 fast ⚡️ and small 🎈 (500 bytes) global state management for React which can be used outside of a React component too!
https://github.com/web-ridge/react-ridge-state
Stick to redux, dont complicate things for yourself :)

What is the good way for child to parent communication using inverse data flow in ReactJS?

I was wondering something about the reverse data flow in a React app.
Considering this question: data flow in react application and this article http://facebook.github.io/react/docs/thinking-in-react.html
We can see that the "normal" way to communicate from child to parent component is using callback passing through this.props.myCallback. (the StackOverflow article is a good example)
My questions are:
I understand the concept but what if we have deeper components? We would have to pass this callback to every component between the top parent component who hold the state and the actual triggering component. And if there is 3 to 4 components between them, I would have to pass the callback using this.props in each component.
Why not using an Event Emitter? I could send an event from the deep child component and then listen to this event in my top state parent component. This way we could avoid all the code between these two.
Please tell me what are your thoughts about this!
I learnt the hard way that it is a good practice to keep as much logic as possible in the highest level in the hierarchy of your components. Dan Abramov well expressed this idea in the article Smart and Dumb Components, where Smart Components are those that hold the logic, whereas Dumb Components are just meant to display.
So yes, the callback mechanism works well when you simply want to update the father's state, or you want the father to do an action whose logic you do not want to belong to the child.
When you have anything slightly more complicated than this I would suggest you go with a Flux-ish architecture of your taste. Flux indeed uses node's EventEmitter to communicate with the components.

Categories

Resources