What is the difference between react usecontext and global variables - reactjs

The function of react context is to facilitate the component to pass values, but it is not responsive. It needs to cooperate with usestate to achieve responsiveness. What's the difference between using global variables and setting a layer of usestate can also achieve the effect of component transparent transmission. I can think of the difference between context and global variables is that context only transmits data to wrapped components, while global variables have no such restriction

props and context are the ways that react has for moving data between components. Built into these are the fact that if you rerender the source component and it has a new value for the prop/context, then the destination component will rerender too. The child component does not need to somehow register an event listener on the props/context, and then set state when the value changes; it's enough that the props/context changed.
If you do a global variable, then yes, it can in principle be available to all components. However, you will need to write code which listens to changes in that global variable (for example, with an event emitter or an observable), and then every component that consumes it will need to set local state when the global value changes, in order to rerender itself.
context only transmits data to wrapped components, while global variables have no such restriction
While you describe this as a restriction, it's sometimes a very useful benefit. For example, suppose you have a Theme object that sets the colors for your app. It's provided via context, and your ui components use it to style themselves.
But you also want to let the user change the theme, and see a preview of the change. Since the Theme is using context, you can create a new context provider that just wraps around the preview part of your app. Components inside the preview will use the modified theme, while the rest of the app behaves as normal.

Related

React useState causes performance issues - the proper way to handle menu interaction

I have an app with a "menu". The "menu" is fairly complex, and the user can open small divs to set parameters that affect the app in real time. The app is structured as below:
Parent div with multiple useState instances to set parameters
- Menu Child Div
- functions to set those state variables are all passed to this div
- parent state is altered using these
- Main div where the results are displayed
- receives the state from the parent div and displays appropriately
The way that it works is that when the user interacts with the menu, the state is altered in the parent and that state change is then passed in the props to the main child div. This is causing performance issues as the app has to rerender everything when something changes in the menu and the existence of so many state variables may be a problem.
What is the best way to handle this? Using the useReducer function instead could be an option, but I am not sure that this alone would solve the problem. How do I make the main div respond to changes in the menu without everything having to be rerendered?
How do you handle interaction between your menus and your main div without having to re render everything?
Would the performance issues be solved by doing the following?
Parent div does not address state
- Menu Child Div
- interacts with redux state to change options
- Main div where the results are displayed
- reads in and reacts to redux changes
If you want a React component not to re-render unless the local state/props are changed, you may consider replacing your React.Component with React.PureComponent.
Whenever you're dealing with State that is being passed around between component orders, you may want to consider managing a global store. You can do this by using tools such as Redux, MobX-State-Tree, or Context API. This is especially useful if you're managing a mid-large scale project.
Resources:
https://ozmoroz.com/2018/09/what-is-purecomponent/
This resource has some great info on common React tools:
https://www.reactnative.express
And of course, there is always React's docs of which you are likely well aware of:
https://reactjs.org/docs/hooks-intro.html

How to hook local state update from global context change

I try to propagate global React context change into a sub component local state.
I need to use updated context value in the sub component for local filtering and various data transformation, but without altering the global context data.
A minimal example is available here:
https://codesandbox.io/s/contexttostate-z1svj
Context value correctly triggers component rendering on each change, but I cannot figure out how to use this change in a local effect hook.

Are There Cases in Which Non-Render-Triggering Global Vars May Be Needed in React?

I have global state working via Context/AppState/AppStateDispatch. I also have component state working via useState.
But there are times when it appears it might be helpful to avoid using these:
We need immediate access to the value in the current function and can't wait for the next render to get it. Storing it via useState/AppStateDispatch would prevent the value from being accessible until the next render
...and, those same values are needed globally throughout the app
...and a useRef would be destroyed on component unmount
In that case, it seems like it might be appropriate to use a globally-available, non-render-causing object to hold state for these items.
It's pretty easy to implement... but it seems non-React-y. Am I missing something?
I looked into this pretty extensively the past few days. Here are a few observations.
In my use case, I'm using an external webRTC service. Their code requires my app to install listeners for incoming calls, responses to publication of video streams, etc. The listers needs to access the component's webRTC-specific variables
At the same time, those variables can't be part of component state or app state, because when updated, their values won't be available until the next refresh, and the rest of the component needs to access them within the current render.
Using an application global var that is apart from React and doesn't trigger a refresh is, of course, kludgy.
Here's the approach I'm using at the moment. So far it appears to be helpful.
Create an application-state object to store all variables related to my component's use of webRTC.
Initialize it via a call to a function, getWebRTCDefaults().
On component mount, copy it from app state to a component-level variable. Note-- it is not in component state -- it's a component-level variable, accessible anywhere in the component.
As such it can be updated anytime within the component and its values are immediately available throughout the component.
When a call starts and ends -- and only then -- I use React context dispatch to update the app state object. I.e. I do not update that object via useEffect as that could cause unnecessary renders.
This approach seems to be helpful. I can unmount the component and when I remount it, it picks up where it left off -- the webRTC video is still running.

Redux/MobX - Do I need to pass data in child components via props in React?

I know It may sound like a dumb question, But I am not able to get this solved in my head. Please bear with me.
In case when we use a state management system in React like Redux / Mob X, I guess the main purpose of these state management techniques is to provide a single source of Data and a more structured approach of updating it.
Say, I am Using a state management library(MobX) for React, And suppose I have a parent component which makes an http API call and updates the MobX store with the API response. Now I need that data in one of child/nested components.
My Question is, Should I pass that data as a prop to child component or should I enable child component to connect with Central Store and directly get that data ?
by connecting the child to store, I am turning the Child into a class component, which is making it more heavy and React optimisations may not apply. I am defeating the whole purpose of a functional component.
Awaiting replies.
Best Regards,
Lalit
This completely depends on the situation. I would suggest splitting your components up in 2 parts:
Components that could be re-used in other projects
(Higher level) Components that are so specific to this project that they probably never will be re-used.
For components of category 1, I would suggest not using mobx store directly, but instead make pure react components. (eg think of a dropdown, or an ajax dropdown component).
For second part components (think of, header, footer, section components specific for your website). just make them directly interact with the Mobx store, so that you can way quicker code what you need (instead of constantly having to prop everything).
addition
For components of category 1 you can always wrap them with the #inject() method. This way for example you could turn a dropdown component into a UserDropdown component that uses the mobx store for its state. (The inject method injects mobx state as props in the component).
const UserDropDownComponent = mobx.inject(stores => ({users: stores.userStore.users}))(DropDownComponent);
// usage:
<UserDropDownComponent />
Warning
For pure components wont always see changes of mobx state. To Fix this you need to wrap the component in an #observe annotation. Or you have to inject the props by wrapping it into: mobx.toJS(yourMobxStateProperty)

state vs props for scenario with separate view and data model

I'm building an application where I would like to provide separate views for same data.
In my current implementation, data is obtained by web service call and persisted in state of App component in App.js. App component hosts (renders) another component called StackEditor, which acts as a view for this.state.components in App component.
UI elements rendered by StackEditor can be moved around, and to synchronize state of App I do it as below:
<StackEditor
components={this.state.components}
onLocationChanged={this.handleLocationChanged} />
In handleLocationChanged I update the state:
handleLocationChanged(e, data) {
this.setState(prevState => {
// event data copied to state here
return {components: prevState.components};
});
}
As state is now updated, this forces StackEditor to be rendered again, as its property components is bound to state as components={this.state.components} (see in the code snippet above).
This all works, but now I started questioning if I'm doing it right.
Q1: Should I be using state instead of props?
It seems that location of component is mutated in principle, although from StackEditor point of view, it is immutable (I can decide that change is invalid and not to update the state in event listener).
Q2: Is it possible to share part of the state between 2 components in React?
If I somehow convert StackEditor from getting components from state instead of props, will I get notification on state changed by child component (StackEditor) in my parent component (App)?
Q3: Also, are props more convenient to use than state in general?
When I created another component following HOC guidelines (https://reactjs.org/docs/higher-order-components.html) I discovered that props are easily forwarded to "wrapped" component, but not state. If I provide a function to call back via property (as I did above), "wrapped" component can easily call it, without even noticing that it's "wrapped". I don't see how I can easily notify "wrapped" component about state change in "wrapper", without writing some extra code.
If you imagine your application to be a tree of components in a well designed app it's usually like this:
the leafs are stateless components . They decide how data is rendered.
the nodes are stateful components. They decide which components and data to render.
Q1: Should I be using state instead of props?
It depends on which category of components you have (node or leaf).
Q2: Is it possible to share part of the state between 2 components in
React?
If you feel that your app has a lot of state that mutates and needs to be used by several components spread over your tree you usually start to introduce an external state management library (e.g. redux). Components can subscribe to your store and become stateless as your store now handles the state.
Q3: Also, are props more convenient to use than state in general?
They solve different problems so you can't really say that. A stateless component is usually easier to understand but has no capabilities to control anything.
Also read Identify where your state should live and When to use redux.
All that is only a rule of thumb. A lot of the time you will have components that have both state and props because they control parts of your app but delegate other parts to their children.
This all works, but now I started questioning if I'm doing it right.
As far as I can see from the code you provided this looks pretty much as it has to.

Resources