I was reading about React-Redux provider in the library docs and i faced 'context instance' prop as one prop for the provider, i couldn't really understand what it means:
context You may provide a context instance. If you do so, you will need to provide the same context instance to all of your connected components as well. Failure to provide the correct context results in runtime error:
Is it the whole store data?? the destination component of data??
Is it the whole store data?? the destination component of data??
No, the context props is a react context instance, which allow you using store directly in its consumer instead of through connect, useSelector or useStore. As its doc, you can either create your custom context or using redux's ReactReduxContext
Related
So I had this thought occur to me today. I've been learning React for a bit, and I often hear the Context API as a shared data source for nested components. You instantiate a context, wrap all the components you want to have access to in that context's provider, and do what you need to with that data inside each component.
My question then is essentially, why do we use the Context API instead of just using a shared reference to a value inside a module? At the end of the day the useContext hook and Context.Consumer require an amount of code roughly equivalent to simply importing a module across all the components that need access to its data.
I'm struggling to understand how using the Context API actually solves any problems that couldn't just as easily be solved with what the browser already provides us, so what am I missing here?
The below question relates to the following sections in the React Context documentation:
Dynamic Context
Updating Context from a Nested Component
Disclaimer: Apologies for all the background information below. It provides context and will hopefully be helpful to future visitors.
What We Know
Link 1
The (default) context value is set to themes.dark (an object that contains two properties: foreground and background)
The default value is only ever used if there are no Providers above the Consumer in the component tree
In this case, there is a Provider present in the top-level component (App)
This Provider (App), passes down its own state as the context value
It is smart to keep the values provided by a Provider equal in structure and type to the default context value (avoids Consumers getting confused)
Thus, state in the top-level component (App) holds an object of the same format as the default context value: themes.light
Conclusion from the above: When a Consumer reads the context, it reads App's state
In other words, we are here using context to pass a parent (App) state deep down in the component tree, without having to pass it through every component in the middle
When state in the top-level component (App) changes, it re-renders and a new value for state is provided to the Consumer
This way, the Consumer reads the parent's state, via context
...
Moving on, we see in link 1 that a function to set state (toggleTheme) is passed down the component tree as a normal prop
Thus, in link 1, context only contains an object that reads state
We are able to set state in the Consumer by passing the setState function as a normal prop from the Provider's child, down through all the intermediate components, and in to the Consumer
Setting the state in the top-level component (App), leads to a re-render of itself, which leads to a re-render of the Provider, which then passes the new App state value down to its Consumer via context
As such, the Consumer always knows App's state, via context
In conclusion, the flow is:
Parent's state is provided as context value to child Consumer(s)
Parent's state is updated by some child
Parent re-renders
Provider sees that context value (App's state) has changed, and re-renders all its Consumers with the new value
Link 2
In link 2, we set state in the Consumer, by passing the setState function within the context
This differs from link 1, where we relied on a normal prop to set state
Questions
We know from the docs that:
Every Context object comes with a Provider React component that allows
consuming components to subscribe to context changes....
All consumers that are descendants of a Provider will re-render
whenever the Provider’s value prop changes.
Let's assume we use a normal variable in App as the context value. We know from the above quote that changing it leads to the Provider re-rendering. Why then, do we bother using state as the context value? What is the benefit of that, vs. just using any normal variable in App?
Both the two approaches above allow us to update state. Why is link 2 incorporating the function to update state within state itself? Could we not just have it as a separate setState function, which is passed to the Consumer via context in an object that has two properties (one is state and the other is the standalone function to update state)?
Let's assume we use a normal variable in App as the context value. We know from the above quote that changing it leads to the Provider re-rendering. Why then, do we bother using state as the context value? What is the benefit of that, vs. just using any normal variable in App?
It's true that when the provider is rerendered with a changed value, any descendents that care about the context will rerender. But you need something to cause the provider to rerender in the first place. This will happen when App's state or its props change (or when you call forceUpdate, but don't do that). Presumably, this is at the top of your application, so there are no props coming in, which means you'll use state to cause it to rerender.
Both the two approaches above allow us to update state. Why is link 2 incorporating the function to update state within state itself? Could we not just have it as a separate setState function, which is passed to the Consumer via context in an object that has two properties (one is state and the other is the standalone function to update state)?
When deciding whether to rerender descendants due to a change of context, react will do basically a === between the old value and the new value. This is super quick and works well with React's preference for immutable data, but when using objects as your value you need to be careful that you're not making new objects on every render. For example, if App is doing something like the following, it will be creating a brand new object every time it renders, and thus will be forcing all the context consumers to rerender as well:
class App extends Component {
state = {
data: {
hello: 'world',
}
}
updateData() {
// some function for updating the state
}
render() {
return (
<MyContext.Provider value={{
data: this.state.data,
updateData: this.updateData
}} />
)
}
}
So the example where they store the function in state is to make sure that the entire value they're providing does not change from one render to another.
Let's assume we use a normal variable in App as the context value. We know from the above quote that changing it leads to the Provider re-rendering. Why then, do we bother using state as the context value? What is the benefit of that, vs. just using any normal variable in App?
When you use state and update it - it does not matter at all if you are using provider or not - all the provider and components under it will update. Thats under official React Context documentation and is wrong. It means changing provider values DOES NOT call consumer updates at all.
You can validate this by making a separate component with state (which would not be inside provider) and assign that state variable to the provider. So when component state changes, value in state changes and in turn provider should notice this and update consumer. Which it is NOT doing.
In order to update components under consumers, you, unfortunately, have to do it manually. Unless your intension is to update everything under the provider.
This is true as of 2021-04-21 under React 17.0.2 - provider value changes are not being monitored and consumers are not being updated sadly. Unless you put all your provider in component with state, but changing its state forces updating all components under the provider. Sadly.
is there a reason people always seem to define these functions at the bottom of every component they are needed?
when ever I create a react/redux project I put these in a /mappingFunctions directory and then import them into the files I need them, thus declaring the functions just once. obviously means the functions include more than necessary but it means they are in just one place rather than defining them a million times.
just wondering why this is not the standard?
Each component/container may need to access different set of variables from redux store and different set of actions. So mapStateToProps and mapDispatchToProps are defined individually for all those components that need to interact with Redux store.
Also you don't need to use mapStateToProps, maDispatchToProps for each component. You can have a balance between passing props down or connecting each component to Redux store.
Check Use Connect or pass data as props to children for more details
Because the state and the actions passed to components are generally different
mapStateToProps - this is callback called by Redux when some part of the state is updated. It is used to update map Redux store changes to properties of your component. Each of your components is most probably interested in different parts of Redux store state. Your container components doesn't need to implement this if they don't need to be updated based on Redux store state updates.
maDispatchToProps - this is callback used to create action closures connected to redux via dispatch. This way Redux store is aware of actions triggered by your component and can update its state accordingly. Your container component will use only handful of actions. It can happen that container component doesn't need to connect any actions, so you would not need to implement this.
If you find yourself duplicating same mapStateToProps/maDispatchToProps across various container components, you should probably reuse same container component on various places of your app and remove such code duplication this way.
I'm developing a react.js project and before the main component is rendered, I call a function that returns an object that all components should be able to access. What is the correct way of doing this in react? Currently, I'm just passing it as a prop to the main component and then I suppose I should have to remember to pass it as a prop to all other components. Is there an easier or better way of doing this?
It seems like you are doing something like Redux. Passing the object as props should be okay. You could make a higher-order component that wraps your components and adds access to that global object via props. This is similar to Redux's connect.
As the expectation in React is application-wide concerns ,like a flux/redux/apollo store, are kept in a root provider component’s context and then accessed elsewhere in the component tree via a Higher Order Component or render props. This provides relief from globals and circular dependencies, and makes testing those components easier.
However, if you have non-component code that will need access to configuration values, you may need to use config global and writing components in a way that accepts config values from props.
see: https://github.com/lorenwest/node-config
Although the term backing instance is referred in react docs a lot, I couldn't get what it means. From react docs :
To interact with the browser, you'll need a reference to a DOM node.
You can attach a ref to any element, which allows you to reference the
backing instance of the component. This is useful if you need to
invoke imperative functions on the component, or want to access the
underlying DOM nodes.
link
This simplified component API is intended for components that are pure
functions of their props. These components must not retain internal
state, do not have backing instances, and do not have the component
lifecycle methods.
link
Because stateless functions don't have a backing instance, you can't
attach a ref to a stateless function component. Normally this isn't an
issue, since stateless functions do not provide an imperative API.
Without an imperative API, there isn't much you could do with an
instance anyway. However, if a user wants to find the DOM node of a
stateless function component, they must wrap the component in a
stateful component (eg. ES6 class component) and attach the ref to the
stateful wrapper component.
A backing instance is the object in memory which represents the node. This is where things like the state are usually stored.
So if you have a stateless component you won't have a backing instance because it is well stateless.
A few points regarding stateless components:
No lifecycle methods
No reference