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.
Related
When I've been developing in pure React.js, I was used to store some data into Redux and set some component to listen to changes in Redux (with useSelector (source). But now I am doing facing the same problem but in different technology. In Remix there's no useSelector with Redux. Yes there is possible to use useState but it have to be under one parent compopnent but I don't have this structure. So is there any solution to force component to re-render when some independent state changes?
Thanks
I've tried to call some function to force re-render but that's not 'nice' solution. I've even thinked about storying data into localStorage/cookies but when they change, components doesn't update (I understand why it doesn't force re-render but I've tried it...).
Redux should still work normally even with Remix, as it's just a state manager. It's entirely possible that all you have is a configuration issue with Redux (I personally dislike Redux for how needlessly complex it into use)
You could try React's own Context for storing state that could be used by several components. Other proven state managers are the likes of jotai or zustand.
Even regular state could work because there's always a root component in remix: i.e. root.tsx.
It's hard to understand what you're trying to achieve. Other ways to update various parts of the UI is using nested routes and . You can access parent and child page data with useLoaderData().
Currently I have my parent components handling all my Axios calls, and I'll pass that data down with props. Should my child components be handling those requests individually in each child component, what is the best practice?
Should my child components be handling those requests individually in each child component, what is the best practice
There is no such rule which says that parent component should get all necessary data and pass that data down to all child components through props.
We can imagine a situation where we have top panel element which shows:
person name
weather temperature
current date
Yeah, if we make requests from each component, then we will have three API calls. So far so good. But on the next day, client says that he wants to show weather temperature in bottom panel. So we will have weather temperature at the top and bottom panel. It means that we will make 4 API calls. And it is not good solution.
What we can do? So if you are going to need to share the state across a lot of components then we could use state management library or useContext hook (it is simpler and easier to understand than Redux). Both have pros and cons.
If your application is not small, we can use state management libraries such as Redux, MobX, Zustand. However, it is completely okay not to use state management library if your application is not big.
Do You Really Need a React State Management Library?
It depends very much on which and how many components need the data.
Data on which many components depend and do not have to be fetched again and again make the most sense in a parent component.
Data which can be used very limited in a small child component should also be fetched in this component.
The same applies to data that is between these two extremes. A healthy balance prevents components that have nothing to do with the data from being unnecessarily misused as middleman. Furthermore, the parent components render all child components as well. It is therefore all the more important to make sure that the calls happen as selectively as possible.
For data that is needed in each component, I recommend a state manager (React's native reducer and useContext). This prevents prop-drilling, because the data can be easily made available in each component.
I currently have a React app that I'd like to use SSR with. All but one component is pretty much static content, making SSR super easy. Everything but the component is rendered just fine and well right now.
My question is how do I go about rendering this component that needs to first get data? Because it's a complex SVG that gets rendered my line of thinking is that having it "update" once data comes in is a bad move, and it would be better for it to just not exist in the absence of data (with an error message).
So here's my plan: I can add a prop to the component to pass in data from a parent rather than keep it as internal state only. So if data is passed, no fetch request in the component is necessary. From there what I can do is take the static bundle output of the app and, when the page is requested, the server will request the proper data just as the component would. Once the data is received, the server can grab the component from the bundle with regex, add the data as a prop, render the component, and stick it back in with the rest of the already rendered static content.
Is this the correct way to do this? It feels a bit complicated, but that might just be how it's done. I'm not sure.
Your intuitions are correct. In current React (17.0), it's quite cumbersome to do SSR with data-fetching inside components.
What needs to be achieved on a conceptual level is that all data dependencies need to be known upfront, ie. before calling ReactDOM's render. This way, one can access the data in a synchronous manner which allows to do one-pass render on a server.
I don't quite follow your idea to "grap the component from the bundle with regex". One way of solving the data dependency problem is to inject the data into React tree from the root component (ie. ReactDOM.renderToString(<App componentStaticData={data} />)) and make the data-dependent component aware of the fact that it can just grab the data from there instead of doing (asynchronous) call. It's important to note that useEffects are not executed on the server.
Another idea to grab all the data dependencies is to do two-pass render. First one is used as a way to collect all resources used, then we await their completion and inject them as static data into send pass.
Third way is to use one of the React frameworks that provide SSR out of the box. You can have a look at (among many others) Next.js or Gatsby. Depending on your setup, this might be easiest or the hardest way to achieve SSR.
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
I am new to react and redux. I have a scenario where there are nested components like this.
A > B > C > D
There is a property used in A component and it will be used in D component. So, I have two approaches:
Get state from redux store in component A and then pass it along as props to all it's child components even though it will be used only in D component.
I should connect to redux store in component D and fetch that property from there.
What is the correct approach?
As Dan Abramov, author of redux says in this issue
Both approaches of passing props down to children or connecting them
to the store are appropriate, however having nested connect()
components is actually going to give you more performance. The
downside is they're slightly more coupled to the application and
slightly harder to test, but that may not be a big issue.
He has also articulated a nice rule of thumb to follow on reddit
I do it this way:
Start by using one container and several presentational components
As presentational component tree grows, “middle” components start to pass too many props down
At this point, I wrap some leaf components into containers so that “middle” components don’t need to accept and pass down props that are
completely unrelated to them
Repeat
He has even tweeted regarding this:
Try to keep your presentation components separate. Create container
components by connecting them when it’s convenient.Whenever you feel like you’re duplicating code in parent components to provide data for same kinds of children, time to extract a container.
So in simple words:
You can use connect() at any level. Doing so makes the component smart, since it knows where its props come from. A dumb component just has props, and they could come from anywhere. A smart component is coupled to redux; a dumb component is not.
UPDATE: react-redux v7 and above
The same concept applies to useSelectors too. You can receive data in a container component and pass on to your presentational components, if multiple of its children make use of the same data
If however the data used by the children is different, you can choose to use useSelector individually within the child component. This will make sure that only those components re-render which actually need to
I would suggest if you are already using redux in your app then set the property in the redux store and fetch it in the component D.
But if the work flow is really simple and all the data is fetched from a single source per view, you can avoid redux as it is for complex state management.