React Js pulling variable from another top level component - javascript

so i have my two different views one with search on it and then after you select the data row you want it changes to the view base which shows you all the data in full. only thing is you have to be logged in to view it but when you change the url it doesnt carry over the logged in value to make it true so it logs you out and your still able to view the data how would i make it carry the data over from the first page to the second one.
doSomething(value) {
this.setState({
isLoggedIn: value
}, function () {
this.state.isLoggedIn
})
if (this.state.isLoggedIn === false) {
this.setState({
searchResults: []
}, function () {
this.state.searchResults
})
}
}
that is what sets the state of isLoggedIn on the first page how would i pass the variable through to the second page as its not a child or any relation to this component.

use redux and create a global store to manage state

Related

How to persist the same data even after useQuery key change and component is unmounted & remounted again

I have been stuck with one issue, let's say I have this below custom react query hook.
export const useGetData = () => {
const { filter } = useSelector((state) => state.filterReducer);
const queryInfo = useQuery(["filter", filter], () => getData(), {
staleTime: Infinity,
cacheTime: Infinity,
enabled: false,
keepPreviousData: true
});
return {
...queryInfo,
data: useMemo(() => queryInfo.data, [queryInfo.data])
};
};
so here I'm actually storing the user's filter state in the global redux store and whenever the user makes any changes this will create a new cache with data as undefined. so since this query has been set enabled to false it will not make an API call and the user has to manually click on the apply filter button in the UI in order to get the data, which actually makes refetch call and gets the data update the existing undefined cache with the data returned from the server.
since this query has keepPreviousData set to true it will keep the previous data in the UI. but in the cache, the new filter has been updated with undefined. So now let's say the user doesn't apply the filter (by clicking on the apply filter button), they just change the filter (which actually creates a new cache), and let's say the user unmounts the component and mounts the component again (using a toggle), the previous data which was showing has gone! (because now it's showing undefined)
Is it possible to keep the previous data if enabled: false, keepPreviousData: true, even if the component is unmounted and mounted back again?
here is the reproduced code sandbox - link
I'm stuck with this issue for the past couple of days not sure how to fix it. Any help on this will be highly appreciated thanks in advance.
The problem seems to be the local state management. As long as the user changes filters, they shouldn't be sent to redux because that drives the query. It is also intermediate state that redux is not interested in. If the user hasn't applied the filter, but it is globally available, you cannot distinguish between filters that have been applied and filters that haven't been applied yet, leaving your UI in an inconsistent state.
The state should likely be kept local in the form only. Once the user clicks apply, you save the state to redux, which will re-fetch the query.
As a side-note, I would automatically enable the query once you have filters. Also, queryInfo.data is referentially stable - there is no need to memoize it:
export const useGetData = () => {
const { filter } = useSelector((state) => state.filterReducer);
return useQuery(["filter", filter], () => getData(filter), {
staleTime: Infinity,
cacheTime: Infinity,
enabled: !!filter,
keepPreviousData: true
});
};
Then, the local state management will look something like this (pseudo-code):
<FilterForm onSubmit={(data) => dispatch(actions.setFilter(data))} />

How to properly clear Vuex state in an application with vue-router?

I have a vuex store which can increase when I walk through pages of my site. Every page has its own store where specific information for this page is stored. I know how to write a function which will be responsible for clearing my state, but I don't understand where to call this function in my code.
Let's say I have 5 pages, where 3 of them own their specific store which should be deleted when I move out of a page, but the other 2 have a common state which should be deleted only when I move out of these pages, but when I move between these 2 - the store should be kept in the state it's now. Data for stores are fetched via AJAX requests.
How do you handle this problem? I was thinking about listening to $route changes, but something makes me feel it's wrong.
My function which clean ups the store (reset_state):
const getDefaultState = () => {
return {
widgets: null
}
}
export const items = {
state: () => ({
data: null
}),
mutations: {
reset_state (state) {
Object.assign(state, getDefaultState())
}
},
actions: {
resetItems({ commit }) {
commit("reset_state");
},
}
}
You should call your function either inside the beforeDestroy lifecycle hook or inside the beforeRouteLeave hook - depending on whether you wrap your route(s) inside keep-alive.

Check if the key in redux store is connected to any component in DOM right now

I have a redux store with a reducer data and using redux observable to fill this data in store. I am trying to load some data in store when component is mounted and remove that data when component is unmounted. But before removing I want to check that this data is not used by any other mounted component. What I have till now is this
Store:
{
data: {}
}
My component needs itemList, I dispatch an action LOAD_ITEMS, one epic loads itemList and puts it in store
{
data: { items: {someItems}}
}
This component has following connection to store -
componentDidMount () {
if (!data.items) {
dipatch(LOAD_ITEMS)
}
}
componentWillUnmount() {
// Before doing this I want to make sure that these items are not
// used by any other mounted componeted.
dispatch(REMOVE_ITEMS_FROM_STORE);
}
mapStateToProps = () => ({
data: store.data
})
One way I tried was to save count of all mounted components which uses items from store in store with a key activeComponents. Like following
{
data: {
items: {someItems}
activeComponents: 2 // count of mounted components which are
//using items from store
}
}
So if there are two components which needs items from store the count of activeComponents will be 2, so items will be removed from store only if this count is one, on other removal attempts just activeComponents count is reduced by 1
But this is very complicated approach, I suppose there must be some better and proper way do this. Any thoughts?
I think your idea with storing the number of activeComponents is kinda the right approach, but you should use a boolean value, that will make it much more simple to handle.
So basically instead of storing activeComponents: 3, you can just do isUsed: true / false

Reactjs render component only when ALL its child done thier render

I have a "slow" loading issue in one of my pages.
That page contains a "root" component - let's call it Container.
My Container makes 2 fetch calls upon a value selection from a dropdown list.
The fetched data (A and B) are passed to a child component (Board).
Board is built from 2 unrelated components - Player and Item and they use A and B respectively as initial data.
It so happens that the Players render process is much more heavy than Item's.
The result is that Item is rendered on the page and after some few seconds Player is rendered also.
My wish is to see both rendering at the same time - how can I achieve that?
I guess it is something should be done by Board but how?
It is also important that this "waiting" will take place every time the value from the droplist is changed (it always there for the users to choose).
Thanks!
There are a couple of ways to do this.
1) Use graphql to orchestrate the loading of data, so that the page renders when all of the data is available
2) Set state values for playerDataReady and itemDataReady. If either of these is false, display a loading spinner. When they are both true (as a result of ajax calls being resolved), then the render will do both at the same time
In the constructor...
state = {
playerDataReady: false,
itemDataReady: false,
}
:
:
componentDidMount() {
// Request player data, using axios or fetch
axios.get(...)
.then(data) {
this.data = data
this.setState({playerDataReady:true})
}
// Do the same for your item data (and update itemDataReady)
}
In your render function:
render() {
if (!playerDataReady || !itemDataReady) {
return <Loader/>
// The data has arrived, so render it as normal...
return ....
You can fill in the details

Why do processes not work for me the second time with vue?

I have a small Vue application, with a parent component which has more components immersed in it, Initially I get some product data from the database, from these elements stored in an array calculates with vue.
It works well the first time, but the second time my data is not reactive, checking the console with vue devtools, the property changes, but on the screen they are not changed.
What can I be doing wrong? , what I do at the end of the first time, is to reset the values of the elements of data () {} in the following way.
this.showModalOptions= false;
this.showModalType= false;
this.udpdateprecios = false;
this.products=[];
this.productsselect= [];
this.productselect={};
this.type= {};
this.obtenerProducts(); //get productos y assign to array products
method obtenerProducts
obtenerProducts(){
axios.get('/api/products/all')
.then((result) => {
this.products= result.data.productos;
});
},
declare data()
data() {
return {
products: [],
productselect: {},
type: {},
productsselect: [],
showModalOptions: false,
showModalType: false,
};
},
I can not add an example that works for me, maybe it is not the way to reset the array or objects with which they stop being reactive?
If as you said, the property changes and the screen stay the same , maybe you should try vm.$forceUpdate() or vm.$nextTick(yourFunction) to refresh the event queue.

Categories

Resources