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.
Related
Where should I put get user data API call which is requesting user data such as username, email from JWT token stored in localstorage.
Should I call it from _app.js pass it to the components or should I create redux store and save these data.
Using redux only for that purpose is an overkill. You should create context and wrap components, which are using this data. Also there is hook called useReducer, combined with context API allows you to achieve redux behavior.
Passing user data down to components directly is not a bad idea if you have only 2 level depth structure which is often not the case.
For this purposes is a nice option to use tools like Redux or React Context API. That way you can access the global state from whichever component you like in the same way, which leads to more readable and maintainable code. For more information about Redux vs Context API, consider looking more in-depth to understand the differences and decide which one is more suitable for your case.
For me personally, the Context API can do the work in more of the cases which is fine. Also, it is already part of React, and it's not a dependency like Redux is.
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.
I'm new to React and I'm trying to figure out the best way to request information from the server based on the URL. I'm using Redux and React Router v4.
Let's say I have a route /foo/:id, and a component Foo that will render something based on id. However Foo needs some server data related to id to do so. I believe the way to accomplish this would be to use mapDispatchToProps to create a function that takes id as input, does some async work, dispatches an action, and ultimately updates the redux state.
My question is: where is the most appropriate place to invoke the dispatch? In this scenario, there's no form submission or button click to kick things off. Originally I was thinking of including a check for the id data in render() and fetching if it was not populated, but this felt wrong due to the side effects.
You can do it in componentDidMount of the Foo component, similar to this example from the Redux GitHub project.
Your intuition is right that render is not a good place to do so. Most people do it in the componentDidMount lifecycle method of the component.
On a relevant note, you will also want to do fetching also in the componentWillReceiveProps method like what they did here. Reason being if your user navigated from foo/1/ to foo/2/, the component is already on the screen and will not be mounted again, hence componentDidMount will not be called again. The fetching for the second user will be done in the componentWillReceiveProps method.
i think the best way to do the dispatch inside the componentWillReceiveProps() which would help you fetch some data before the component renders
It seems your use case is well-captured by the react-refetch package which you can find here. It provides a higher-order component that allows you to specify dependencies at specific API endpoints and then resolves them when a new instance of your component is created.
Importantly it injects the data into your components props using a synchronous abstraction of a promise called a PromiseState. This will allow you to conditionally render your component depending on whether the data is say pending, fulfilled, rejected, etc.
This is not attached in any way to Redux, it skips that layer entirely, so do keep it in mind that the response is directly injected into the component and does not go through your redux store's state.
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.
I am new to Relay and I am currently trying to use mutations. In my use case, I have a form made up of several React components and I want to capture the changes/mutation of each component, combine them in the parent component and then commit the changes to GraphQL server. How can I do this?
The examples that I have seen so far all deal with the mutation being used and committed in a single component. I want to use the same pattern that is used for querying where fragments are localised within the react component and then they are combined to create a query for server.
I had asked the same question on GitHub where #yachaka and #josephsavona answered.
Here is #josephsavona's answer:-
...a straightforward approach would be to accumulate all of the changes from child components in a parent component (using callbacks and local state or something like Redux) and then make a single mutation when the user saves/commits the changes.
One pattern is to use applyUpdate to optimistically apply each individual change, then roll all those optimistic mutations back when applying the final mutation.
See https://github.com/facebook/relay/issues/1461#issuecomment-264662371 for the full discussion.