Can ApolloProvider be made to provide to state instead of props? - reactjs

Redux's Provider component and connect function provide a reference to the store's state to wrapped components via mapStateToProps. As mentioned in the lovely article How to Build a Redux, this is done so that you don't need to refer to a global store object or pass data endlessly down the DOM.
This has a great advantage: the store state is DOM agnostic. You can put any two elements anywhere on the page and provide them with any data you want from the store. If you have a form for customer search and a list of customer search results... the relationship of these presentational elements doesn't affect their access to data.
As far as I can tell, Apollo-react's ApolloProvider does not subscribe to this principle. When I wrap a component with a query using graphql, the results of that query are provided as props to the wrapped component. If those results are needed elsewhere in the app, they must be passed manually or stored on a global reference. In particular, props returned from a graphql query cannot be passed up the DOM.
Is there a way of making ApolloProvider "provide" query results to the rest of the app in the same way redux's Provider does? Do I need to build this functionality myself? Or, better yet, am I misunderstanding something?

Apollo uses Redux to cache the graphql query results. Essentially if you have multiple components that need the same data, just use Apollo to wrap each of them with the same graphql query. You can even go as far as defining the graphql connector once, and using that same connector to wrap your N components.

Related

What is the best way in React Native to store global app data used in many screens?

I am making a React Native app and I need the user data (fetched from firebase database) to be available right after the first screen and in many other screens.
As it is complete user object data, I do not think passing it via the navigator props is suitable. So I am searching for alternatives.
Can someone help ?
The best way to store and share global data is Context API or Global Context .
This new API solves one major problem–prop drilling. Prop drilling is the processing of getting data from component A to component Z by passing it through multiple layers of intermediary React components. The component will receive props indirectly . Context provides a way to pass data through the component tree without having to pass props down manually at every level.
To create a context, we use React.createContext which creates a context object. You can pass in anything as an argument to React.createContext.
import React from "react";
const YourContext = React.createContext("value");
To make this context available to all our React components, we have to use a Provider.
Every context object comes with a Provider React component that allows consuming components to subscribe to context changes. It is the provider that allows the context to be consumed by other components.
In order to create a provider, we have to import our Context.

what's the best way to share user data between components?

I have a query i.e:
query me {
me {
username
email
}
}
now I need to share this data between components.
I guess I can:
create HOC withUserData and wrap other components
create a render prop component and wrap other components jsx
else?
It depends on where are places you want to share them, I mean if you want to share data in the same branch of the component tree, you can have a Container Component at the top ( Which holds your state and pass the data has props to the levels below).
If your components branch is very complex and it needs to travel down many levels then its a pain and not recommended too, in this case, consider using Context API
https://reactjs.org/docs/context.html
I would not recommend a HOC for this, HOC is not meant to share data, its meant to share re-useable functionalities.
Please check this, this has a bunch of best practices https://www.toptal.com/react/tips-and-practices
Well REDUX is another way but I would not recommend using REDUX looking at your need.
When to use REDUX?
Basically, you need to be using REDUX, when keeping the state in a top-level root component is no longer sufficient, like for example : ( you have two branches out from root component, one of the child components in branch A wants to access some state in branch B's child, then you need to move it to the root component and again pass it down, such cases are apt for REDUX ).
HOCs and Render props are not something that you would use to share data among components since each wrapper will have a different instance of the data whenever you create a component like
const MyComponentWithData = withUserData(MyComponent);
You would use HOCs and Render props mostly to provide a functionality which can be relevant to more than one components like detecting click outside of the component, or a PrivateRoute for authentication and so on.
However in order to share data you have options to use React Context, Flux or Redux. With the usage of React redux you can keep data in a store and read and update data from the components that want access to it. However if your app is not using Redux and you would want to share data only for a part of the application, you can simply make use of React Context. For more details on how to use it, you can read about it here

ReactJS: Properly handling user logged in data?

So, currently, we send an API call to get user authentication data. User ID, Client ID, etc...
Then we pass this data to redux and load the user data into React Router through connect() and mapStateToProps...
Then each route gets this user data and passes it to the rendered component through props...
Then, in a lot of our components, we make more API calls using the user data.
However, most of the time, this data shows as an empty object {}
Is it best to pass this data down to components through React Router, or should we be getting the data from redux and mapStateToProps on each component that needs the user data?
I would pass the info from the store to the components that need it using mapStateToProps or a container.
Although this could be considered subjective, there is a real advantage of using containers instead of passing the props from Router: By properly using containers you can pass to components exactly the properties they depend on, nothing else, because any additional properties passed along through components that do not really affect how those components render or behave could be causing unnecessary rendering. Using connect you can "inject" the store information anywhere in the element tree, but using Router you have to pass it down from component to component.

Relay container with no data

I'm building an app as my first real foray into React, Relay and GraphQL, using Relay Modern.
The basic case is, I have a login form component that doesn't really need any data; that is to say, the component renders a form, and has a corresponding mutation, but doesn't need to query anything.
It seems that providing a Relay style query fragment is a necessity when calling createFragmentContainer, which in turn ensures that the this.props.relay will not be null in the context of the component.
Right now, I'm using a standard (non-Relay) React component for the login form, but as a result I'm unable to access the Relay environment to pass it through to the mutation.
My question - is there a way to essentially pass an "empty" Relay fragment? Or is there some better idiom that is recommended in this case?
You actually just use a normal component then create a mutation file with the mutation in it. Run the relay compiler to create the graphql fragment for the mutation and then call on the mutation in the form submit. The mutation does need your environment. Here is the relay modern docs:
https://facebook.github.io/relay/docs/mutations.html
You will need to store the result of the mutation somewhere and then append the auth token to your next requests, but that shouldn't be terribly hard to do. Just onCompleted and store the result somewhere.
Your environment should be a seperate file that you import for mutations and query renders. Only paginationContainer inherits encironment from a queryRenderer.

using connect's mapToProps vs reading and dispatching to the store as a global?

What's the difference between A) using the connect method of connecting state and dispatch function to a component and B) simply having functions in a component that do the dispatching as well as accessing the store as a global directly?
(Not ES2015)
Quoting from the Redux FAQ on importing the store directly:
While you can reference your store instance by importing it directly, this is not a recommended pattern in Redux. If you create a store instance and export it from a module, it will become a singleton. This means it will be harder to isolate a Redux app as a component of a larger app, if this is ever necessary, or to enable server rendering, because on the server you want to create separate store instances for every request.
I also recently wrote a Reddit comment on why you should use React-Redux and connect instead of talking to the store directly. Quoting that:
First, while you can manually write the code to subscribe to the Redux store in your React components, there's absolutely no reason to write that code yourself. The wrapper components generated by React-Redux's connect function already have that store subscription logic taken care of for you.
Second, connect does a lot of work to ensure that your actual components only re-render when they actually need to. That includes lots of memoization work, and comparisons against the props from the parent component and the values returned by your mapStateToProps function for that component. By not using connect, you're giving up all those performance improvements, and your components will be unnecessarily re-rendering all the time.
Third, by only connecting your top-level component, you are also causing the rest of your app to re-render unnecessarily. The best performance pattern is to connect lots of components in your app, with each connected component only extracting the pieces of data it actually needs via mapStateToProps. That way, if any other data changes, that component won't re-render.
Fourth, you're manually importing the store into your components, and directly coupling them together, thus making it harder to test the components. I personally try to keep my components "unaware" of Redux. They never reference props.dispatch, but rather call pre-bound action creators like this.props.someFunction(). The component doesn't "know" that it's a Redux action creator - that function could be a callback from a parent component, a bound-up Redux action creator, or a mock function in a test, thus making the component more reusable and testable.
And finally, the vast majority of apps built using React and Redux use the React-Redux library. It's the official way to bind the two together, and doing anything else will just confuse other developers looking at your project.
For more info, see:
The Redux FAQ section on performance
The Redux FAQ entry on connecting multiple components
The Redux FAQ entry on components re-rendering too often
The Redux FAQ entry on importing the store directly
The Redux Performance section of my React/Redux links list
And finally, my blog posts Practical Redux, Part 6: Connected Lists, Forms, and Performance and Idiomatic Redux: Why use action creators?.
Source: I'm a Redux maintainer, and author of the Redux FAQ.

Resources