Updating Component State from Helper Component - javascript

I know there are tons of solutions for this using Redux and other state management packages, but for the purpose of my project, I'm not really relying on a lot of state change
Now my issue lies in the following; I'm logging the user in using several APIs, one of which is a chat API. The helper logs the user in and then sets its own state with two objects returned.
On the Chat page, in the render() function I have conditionals for certain elements to be rendered based on the presence of the two states returned from the helper library, if they exist pass them as props to child components.
I understand I can use globals to set a global.chatReady from the Helper and just use that, but since the login takes some time, if the page is loaded before the global.chatReady is set I would need to navigate away to update the UI.
There is no link between the Helper and Chat and I'm not sharing any states using react-navigation.
Any ideas? o.O

Create a state in app component , something isChatHelperReady, pass it down the Chat component, also pass down an update isChatHelperReady method to login component from app component. In login component after import helper library, update the isChatHelperReady state in app component using the method

Related

React - Fetch data in the parent or inside its childs?

Note: I am not using Redux (only Context + Hooks)
Introduction
I have a screen "Profile", that renders a TabView.
This TabView, renders two components as scenes:
UserPosts
UserInformation
My Profile screen, fetches the user data from my database, as it has to render some stuff that depends on this data.
Also, it is passed down via props to my "UserInformation" component, as it just renders the user data. So... there is no data fetching in my "UserInformation" component.
In the other hand, my "UserPosts" component is responsible of fetching the user posts, as it renders a component "UserPostsGrid" which renders those posts with pagination (endless FlatList).
Note: Data fetching is performed in custom hooks, not directly inside
the component (also, those hooks manages the respective stateful
data).
Problem
The main problem comes when I need to refresh the user data and the user posts when the user pull-to-refresh inside the "Profile" screen.
There is no problem for this screen to fetch the user data, as I have said before the "Profile" screen is responsible of that action.
But the posts are the stateful data of my child...
Multiple solutions?
I have thought to solve this problem using the current solution:
React.forwardRef() + React.useImperativeHandle()
With this, I will be able to pass a ref to my "UserPosts" and use imperative programming for accessing the data fetching method: userPostsRef.current.refreshPosts();
I have never seen other scenarios for solving this problem like this, but it should work. Instead, other coders implement a ContextProvider to handle all the data and be able to access it wherever they want. The main problem I notice here is: extra memoization + extra re-renders.
Another solution might be to implement all the data fetching inside the parent, and pass the respective callbacks via props to the child. The main problem I notice here is that we are creating some kind of "God Component" and we might have multiple lines of code...
My question
Is it an anti-pattern or a bad practice to implement the first solution ?
To answer your question:
Yes, it is an antipattern in React, because React is built around the idea that you specify the state of your app, and then let React render the components depending on this given state.
If something should change, you are supposed to specify a new state that represents the difference to the old state.
Refs should only be used if there is no other option. Basically, if you use Refs you say "I don't want to use React for this specific part of my code".
As always, imperative code using refs should be avoided in most cases
To use state instead of commands:
I would approach this kind of problem by trying to translate the imperative action into some state of information.
The user says "get me the latest data", that is a command, i.e. imperative.
Now I would ask "what is the user telling me about the state of the data right now ?"
An answer would be "this data is not up to date anymore", and this can be expressed as a state, and passed around via props.
A solution for your problem:
E.g. you might use a prop needsUpdate, which is set to true when the data should be updated, and to false when fetched.
To avoid unnecessary renders (setting needsUpdate = false would cause another call of e.g. useEffect, even if nothing happens there), I probably would use a child component prop like latestUpdateRequest and a child state like latestUpdate which holds a counter or timestamp, and then compare if(latestUpdateRequest > latestUpdate).
To inform the parent about the change just pass a callback function like dataUpdated() as a prop.

Updating data on a Vue component shared between 2 routes

So basically, i have declared 2 different routes and set them to use the same component.
How do i go about updating the data (different API requests based on route) in this component.
I managed to make it work by calling a method this.updateData per say and calling this method on created lifecycle hook and also calling it on watching the $route.path property, and it works but it seems a dirty way to make it work to me, and i might be missing something.
Edit: Im using just Vue js for Simple Page Application, no other frameworks nothing fancy.
For anyone running to the same problem, vue.js tries to reuse components instances as much as it can so basically unless you have a key unique attribute on the component it will point to the same component instance.
So to have a different instance for everytime you use that component add a key attribute which has to be unique. e.g.
<router-view v-bind:key="$router.path" />
In this case it will use the path as a key so that for each route you use a shared component it will create a new instance and you can access the created() lifecycle hook on each one.

React Router - Mobile First: Don't unmount the current component until the new one is ready?

TL;DR: When transitioning pages with react-router v4, how to keep current component until the new component is ready i.e. it made its ajax calls and fetched necessary data to display?
Currently react-router v4 works like this:
User clicks link
Route changes
Unmount the current component & mount new matching component
Ajax calls made to fill components data
However if we think of mobile-first approach, the workflow should be:
User clicks link
matching component is mounted, hidden, being initialised via its ajax calls in componentDidMount/updated
initialisation done, component and its data are ready
Change URL, unmount the old component and display the new one.
Changing URL could be after user clicks the link or after the new component is ready.
By using redux we can achieve this by:
Make all components stateful, have componentXLoad() actions for each
Instead of route change, fire these actions and inside the actions change the url after the component's data is fetched
However, I believe we do not need to go all the way and make every component stateful and generate lots of actions for every page transition.
Idea I have was:
User clicks the link
Route changes, new component is being initialised
If new component's render() method returns null, don't unmount the current component
When new component is ready, rendering non-null, unmount the old component and display the new one.
I believe this is theoretically possible.
Is there already a library doing this?
Or is this something easy to do with React Router v4's API?
Also:
What are the implications on this on SEO, any chance Google considers as cloaking to penalise the site?
I've found this library https://github.com/faceyspacey/redux-first-router, seems it can do this by making everything stateful, but again for something this simple seems like an overkill to switch to that.
Thank you
If you need it only for this specific case I'd say try this:
From component A fetch the data you need to fetch (maybe show some indicator while fetching)
Transition to component B passing the data as custom props
Component B renders initially with the data

React router - views with dependencies

In my application, there are views with dependencies. For example, in one view a user could select an item from a list (generated on the server), and in next view the user would perform operations on the item. The item is passed to the second view in props. I'm moving to using react router, but there are some difficulties:
I can't use props for transferring data anymore. What would be a preferred way to pass data? Do I have to use redux?
Users can navigate from any view to any other view by directly using url. However, some transitions don't make sense: e.g. user navigates to item editing view from somewhere else, and therefore does not have an item selected. Is there a way to limit allowed transitions?
This is a very broad question, but I'll take a stab at it.
Can you use Redux? Sure, Redux is good for centralizing your state which can easily be shared among your components. As far as limiting the url's they have access to, I would use your reducer to look at your current state, if you're using Redux and if data is not there, meaning they should not be at this step, use a javascript redirect to where they should be instead.
Finally, you don't have to use Redux to share data between components this could be done by setting global variables your components can access, but cross component communication is where Redux shines.

React, best way to deal with fetching when navigating between routes containing same component

Basically, I would like to fetch the latest data every time user navigates to different tab. For example, I have summary page and details page for customers, which both includes the same customers container component. I'm doing my initial fetching in componentDidMount function, which doesn't get triggered in route change, as component stays in the DOM. Component necessarily doesn't receive new props either.
One solution would be to customize router link with fetch action being dispatched based on the href, but I'm pretty sure this is an anti-pattern, as it complicates code a lot, is hard to maintain, mixes concerns, and may result in a double fetch if target route didn't contain the component already.
Does React provide any lifecycle hook or mechanism that allow me to fetch in response to navigation event alone?
I'm using React-router-component and Redux.
As far as I understand both tabs happen to contain the same component and so React re-uses the DOM and doesn't create a new component instance, right?
You can use React's special key prop to force React to replace a specific instance.
E.g.:
<div className="tab-content>
<div key="tab-1" className="shared-component-across-tabs">
shared-component-across-tabs
</div>
</div>
And in the second tab you'd use key="tab-2".
Otherwise your route handler component will receive props.location.pathname from the router. You can also implement componentWillReceiveProps and check if the pathname has changed and re-fetch the data in that case.

Categories