In the root component, I have Apollo Query which retrieves data from the server then I want immediately dispatch this data to redux store and then use it in child's components on their first render.
So the scheme is like this :
<ApolloProvider>
<ReduxProvider>
<SomeChildComponent /> --- Can be a lot of nested components
</ReduxProvider>
</ApolloProvider>
Now I am using React.Context to pass data from Query to all child components and do other stuff with the local state by redux. But I need that query result to be in redux store.
So where would I place the dispatch method for this data?
I can't use componentDidMount because I need to handle this data in children before their first render. And also why I need componentDidMount for data which has already fetched and is ready to use.
I see the only way to dispatch it in the render method but I understand that is antipattern at all and can't find information about my case because every question are about fetching data via redux but I have it already so how to deal with this?
You can pass a function to the onCompleted property of the query component, it receives the result data as the first argument. From there you can dispatch your action.
Related
I'm just new to React Hooks, and playaround with it.
Just wondering if there any solutions that I could use useEffect to fetch data several times after componentDidMount.
Normally we use useEffect to fetch data based on some props change by passing them.
useEffect(()=> {
fetchApisomefunction()=>{}
},
[]); // normally do this for componentDidMount
How can I fetch data again after that?
UPDATE
callback function could solve this.
Assuming that you are not using Redux or Context API,
so component A and B are not communicating to each other directly.
On the other hand, there will be a parent component which joins those two components.
As you've said, component B will post the data, and that should change parent's state.
Since react child component is being re-rendered whenever its parent component's state or props change, component A will also be re-rendered.
So all you have to do is to use useEffect without second parameter [].
Actually it is not the question of using Hooks, but the question of react component structure.
Keep in mind that the two child components should not directly communicate to each other.
I am new to React and want to understand the difference from classic MVC.
I want to create a simple components that loads some data initially and renders let say a grid.
On some state or prop change it will reload the data and re-render.
What is the best approach in react from below two options?
using the lifecycle events to load the data, update some state and render while in another event will show some loading opacity.
Work with redux and react-redux? but in all example I cant see API calls.
Is this the role of a middleware (Thunk?)?
Will appropriate an explanation.
Both the approaches are correct. It depends on your use case. If you can avoid using redux in your app, use the lifecycle methods to make API calls (also called subscriptions in react documentation). If you think your app has many components and different components needs to share a state, then use redux.
You should also look at React hooks https://reactjs.org/docs/hooks-reference.html
You can use Effect Hook https://reactjs.org/docs/hooks-effect.html to make API calls and update your component's state.
Update:
Both Thunk and Sage are used to manage side effects in your application (making API calls from here). I've used saga, I don't know much about thunk.
How you would use redux-saga:
Say if you want to get some data for display on a button click, this is how it works:
On button click you dispatch an action, say GET_DATA
Your redux reducer will change some state on this particular action, say isLoading=true
You can use isLoading in your component to show a spinner/overlay
At the same time saga will listen to GET_DATA action and make the API call
If success, from Saga you'll dispatch an action, say GET_DATA_SUCCESS with the data from API call
Reducer will change isLoading=false and set the data in state, say apiData = { ... }
If failure, from Saga you'll dispatch an action, say GET_DATA_FAILED with the error code/message
Reducer will change isLoading=false and set the error in state, say apiError = { ... }
You can now use isLoading=false in you component to remove spinner and display the data (apiData) or error (apiError) in you component.
You can go through this tutorial to learn more https://redux-saga.js.org/docs/introduction/BeginnerTutorial.html
I've been learning React for the past few weeks and I'm struggling with a way to fetch a collection of data from server and presenting it using Redux.
What I have:
I have a <MoviesList /> component which renders a list of <Movie /> components inside it.
What i need:
I need to fetch these movies from a server and store it in my state.
What I'm struggling with:
If I create a container component, I'll use mapStateToProps to pass the movies from the state down to my <MoviesList /> component, but first I need to fetch it from the server, so I thought that I should do it in one of the container component's lifecycle hook, but then I'll have a movies prop (which should be validated with PropTypes) both in my <MoviesListContainer /> and <MoviesList />, which will force me to write a big prop validation in both components, which doesn't look right at all for me.
This wouldn't be a problem if I were to simply spread the props in the container using a function component, but since I need to fetch the movies in the lifecycle hook, it needs to be a class and I need to specify the props in both files.
So what would be the best way to achieve this?
Should I fetch these movies in a different place? Should I take a different approach for fetching it and avoiding these duplications? Or maybe I really should do the validation in both files?
Thanks everyone!
What I have done in the past is to have a function property which is called in the componentDidMount lifecycle event:
componentDidMount() {
this.props.onMount();
}
That property is mapped in the container using mapDispatchToProps to a thunk or some other async action (see the Async Actions documentation).
For a more sophisticated alternative see Redux First Router which allows to dispatch async actions from the router.
#JCE is right, you need to look into Async Actions. If you want to fetch the data and store it in Redux before passing it to your component, you must use a side-effect library (redux-thunks, redux-sagas, etc). The reason is that Redux actions are synchronous by nature and fetching an API is an asynchronous operation. The side-effects libraries will help you achieve that.
So in plain react, setState triggers the render method. Now, about Redux, let's say I fire an action, the state returned from the reducer(s) is totally new, so it sounds like every component should get updated, though I know it's not true because when I debug my app I can see it, plus it sounds like awful performance. So my question is, does redux look in each component what state slice it needs? in mapStateToProps? and generally how does Redux decide when to call the render method?
I know Redux has optimizations in it... thanks...
A Redux store offers a subscribe() method. When you use connect(), it generates wrapper components that automatically subscribe to the store when they are created. Each individual connected component is a separate subscriber.
When an action is dispatched, the store runs all the subscription callbacks. The wrapper components then call store.getState(). As a first check, if the root state object is === identical to the previous one, the component will stop there. (This is one reason why direct mutation of state in a reducer is bad.)
The next step is to call the provided mapState function and pass in the current state object. The wrapper component then compares the contents of the object returned from mapState against the contents of the object returned last time, using a shallow equality comparison check. If any of the contents have changed based on that shallow check, then the component knows it needs to re-render the "real" component with the new data. (Again, the "shallow" check is another reason why mutation is bad.)
I'm working on a redux/react app. We started with very few "connected" components (ie, components that access the redux state and dispatch actions directly). This resulted in every component passing down way too many props to all their children, and subchildren, etc, and the top-level "connected" components becoming god classes.
So, we're making many more components connected, and able to directly access redux state and dispatch actions via mapStateToProps and mapDispatchToProps. It's much nicer, and recommended by Dan Abramov here: https://medium.com/#dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0#.lye71jwmx
My question is, is it OK for a child component to fetch data from the state tree, assuming it's parent has sent the action which made the actual API call to get that data into the state tree?
To give a concrete example, using the classic "blog" app:
A <blog id=123/> component will render a blog post. It will make an API call that, in one hit, fetches the blog and it's nested comments as JSON.
That component will render a <comments blog_id=123 /> component. Is it OK for that child component to just assume that the parent has taken care of the API call to fetch the blog and it's nested comments, and therefore just fetch the comments from the state tree, and gracefully render nothing if the data doesn't exist yet (ie, the API call is still in progress)?
If not, what's the alternative here?
I understand in this contrived example, you'd probably just pass comments down as props. But in my real life example, it's much more complex.
So the question is, is it bad practice for a component to say "I'll render stuff from the state tree - but whoever uses me must make the API call in order for me to work properly"
Of course that's OK. That's how I'd approach it.
With your example the child component won't render anything until the appropriate props are passed to it or state connected to it. You can pass this down to this child or fetch it from the Redux state tree, what ever works in your case.
If there are many child components or the target child is deep within the children I usually try to avoid passing down props. It's probably ideal and less cumbersome to fetch it's props from the state tree over passing state from child down to child and so on.
Take advantage of the mapStateToProps function to only pass defined props and allow the component to render what it's been given.