Given the following Array of objects how would one update all of the qty's in each of the nested "locationData" Arrays Objects? By all, I mean not just all in the Object, but all in all Objects. The base object is say an Item and the locationData is locations the items are in.
What I am doing is displaying all Items with the locations to the user and the user can then click different buttons to distribute the un-allocated Quantity to the locations, which will update all of the objects with the chosen distribution.
Would I loop through the data in the React component and do a dispatch for each Item with a new locationData Array, replacing the old one?
Would I loop through the Items in the Actions and then call the Reducer with an entirely new Array of items with the new locationData?
I can do it with or without ImmutableJs, but I am not sure the best way to do this.
[
{
"isSelected":false,
"itemid":"2557",
"name":"Accessories : Awesome Cable",
"quantity":6000,"quantityByCase":600,
"locationData":[
{"id":"5","name":"QA Location","enabled":true,"percentage":"200","shipcarrier":"","shipmethod":"","qty":0},
{"id":"7","name":"Single Bin Location","enabled":true,"percentage":"50","shipcarrier":"","shipmethod":"","qty":0},
{"id":"1","name":"Warehouse - East Coast","enabled":true,"percentage":"","shipcarrier":"1","shipmethod":"92","qty":0}
],
"unAllocatedQuantityByCase":600
},
{
"isSelected":false,
"itemid":"40",
"name":"Accessories : Crusher Game Pad",
"quantity":50,"quantityByCase":50,
"locationData":[
{"id":"5","name":"QA Location","enabled":true,"percentage":"200","shipcarrier":"","shipmethod":"","qty":0},
{"id":"7","name":"Single Bin Location","enabled":true,"percentage":"50","shipcarrier":"","shipmethod":"","qty":0},
{"id":"1","name":"Warehouse - East Coast","enabled":true,"percentage":"","shipcarrier":"1","shipmethod":"92","qty":0}
],
"unAllocatedQuantityByCase":50}]
Currently, I am doing the the calculations in my reducer EVEN_DISTRIB, but this does not feel right. What I am doing is taking the entire state and mapping it to the items variable. items.isSelected is hard coded to true at the moment for testing. I then do an even distribution of the 'unAllocatedQuantityByCase' for each item and then lastly return all of the items and the new state for this reducer. There will also be weighted and like item distributions later, but wanted to get the even distribution right before proceeding further.
export default function (state = [], action) {
switch (action.type) {
case types.PO_RECEIVED:
return state.concat(action.payload);
case types.EVEN_DISTRIB: {
let items = state.map(item => {
item.isSelected = true;
if (item.isSelected) {
let quantity = item.unAllocatedQuantityByCase;
let updateLocations = item.locationData.filter(location => location.enabled);
let remainder = quantity % updateLocations.length;
let divideqty = (quantity - remainder) / updateLocations.length;
let loc = updateLocations.map(location => {
var tempQty = divideqty;
if (remainder >= 1) {
tempQty++;
remainder--;
} else if (remainder > 0) {
tempQty += remainder;
remainder = 0;
}
location.qty = tempQty;
return location
});
item.locationData = loc;
}
return item;
});
return items;
}
default:
return state;
}}
Should these types of calculations be done in the reducer? or should I do them in the component and then call the action with this as the payload? or is there a better way to do this... Normalizing the data structure and then just updating all of the locations. I guess my question is where do these types of calculations take place in a React/Redux app?
Actions: are functions that just return an action object. no logic in actions.
Would I loop through the data in the React component and do a dispatch for each Item with a new locationData Array, replacing the old one?: this just causes unnecessary re-renders cause the state will change each time you dispatch.
show some code
make your question clear so others can learn from it. and please show some code of what you are trying to do or be clear and to the point in your explanation.
looking forward to helping you.
First, the general suggested approach for organizing nested or relational data in a Redux store is to normalize it, much like tables in a database. That makes your state flatter and easier to manage. See Redux FAQ and Querying a Redux Store for more information on that concept.
Second, while it's up to you to decide how exactly you want to split your update logic, generally that work should be done in action creators or reducers, but not in your components. Redux FAQ gives some suggestions on how to think about splitting that logic. Some people will do all the work in their action creators and leave their reducers to simply merge the action contents into the store, others will have the action creator just dispatch and let the reducer do all the work. I personally am somewhere in the middle-ish - I try to put sufficient info into the action for the reducer to do the work, and am willing to let the action creator do needed prep calculations, but prefer to keep the contents of the action relatively minimal.
Third, your current reducer logic looks overly complicated. At a minimum, I would suggest breaking it up into smaller, simpler, pure helper functions that are easier to think about. Also, remember that with Redux you should update your data "immutably", ie, always make copies and modify the copies, never modify the original versions. The line location.qty = tempQty; appears to be directly mutating some of the original data, and that will generally cause your React components to not update properly. (The item.selected = true line does so as well, obviously.)
Related
I am learning Redux Toolkit. From a React POV it seems very intuitive to access whatever part of the state you need from within useSelector using an inline arrow function, and then conduct any calculations. As an example consider a cart item with its data (like item count) in redux store.
function CartItemCounter({ itemId }){
const cart = useSelector(state => state.cart);
const itemInCart = cart.items[itemId];
const count = itemInCart?.count || 0;
return <div>{itemId} - {count} nos</div>
}
But I'm seeing all this information saying you should define your selectors beside your slice, use createSelector and all. What is the right way, and why is it better?
The information that is out there is essentially talking about different levels of optimization while using useSelector.
What you need to understand before anything else, is how useSelector works internally.
How does useSelector work?
When you pass a function to useSelector (obviously inside a react component), it essentially hooks on to the global redux state. Whenever any change happens in any part of the global state (i.e. when dispatch() is called from any part of the app), redux will run all the functions you passed to useSelector in your app, and perform certain checks.
Redux will take the result from each function, and compare it to the value it got the last time it ran the same function.
How does it make this comparison?
It uses a reference equality for this comparison. So if redux has to think that the result of the function hasn't changed, either the value returned from the function has to be a primitive and equal.
4 === 4 // true
'itemA' === 'itemA // true
Or, the value returned must be a derived data type (arrays, objects), with the same reference. So essentially the same object.
const x = { name: 'Shashi' }
const fn1 = () => x;
const fn2 = () => x;
const fn3 = () => { name: 'Shashi' }
fn1() === fn2(); // true
fn1() === fn3(); // false, because the objects are different, with different references
In practice, redux changes the wrapping object if either a key (or key of a nested object) is changed, or you manually change the entire object using a dispatch action (This is related to the immer library integration). This is similar to how you would do in regular React.
/* See how most keys are spread in, and will hence maintain reference equality.
While certain keys like 'first', 'first.second', 'first.second[action.someId]'
are changed with new objects, and so will break reference equality */
function handwrittenReducer(state, action) {
return {
...state,
first: {
...state.first,
second: {
...state.first.second,
[action.someId]: {
...state.first.second[action.someId],
fourth: action.someValue,
},
},
},
}
}
Otherwise it maintains the same objects within its state, and returns the exact same objects with the same references, when you access them. To verify this, if you access your cart twice, its literally going to be the same object.
const cart1 = useSelector(state => state.cart)
const cart2 = useSelector(state => state.cart)
cart1 === cart2; // true
What does it do with this comparison?
If the comparison returns true, i.e. the new value is the same as the old value, Redux tells that instance of useSelector to chill tf out, and not do anything. If it returns false however, it tells that component to re-render. After all, the value you are accessing from state has "changed"(according to Redux laws), so you probably want to show the new value.
With this information, we can make change the kind of function we pass to the useSelector, in order to get certain optimization benefits.
Optimization Levels
Level 0: Accessing slice data inline
const cart = useSelector(state => state.cart)
// extract the information you need from within the cart
const itemInCart = cart.items[itemId];
const count = itemInCart?.count || 0;
This is not a good way to access the data. You actually need a subset of the data from the cart, but you are fetching the whole thing, and doing the calculation outside the selector.
Problems:
When you put stuff like this inline, what happens if you change the shape of your data in the future? You have to go to every place that uses useSelector and manually change it. Not so good.
More importantly, every time any part of the cart changes, the entire cart object actually changes. So Redux sees your component that asks for the cart, and thinks
The cart has changed. This component is asking for the cart. It should probably re-render.
BAM Every single instance of this component rerenders. And for what? The count of the item you're referencing probably didn't change. So ideally there shouldn't have been a re-render.
Level 1: Centralize the selector
An easy optimization is to put the selector function in a centralized location next to your slice. That way, if your data shape changes in the future, you can just change it in one place, and your whole app (wherever it uses that data) will work with the new shape.
// inside or next to the slice file
const selectCart = (state) => state.cart
//...
// somewhere inside a react component
const cart = useSelector(selectCart)
Level 2: Access the relevant data
Since redux is comparing the results of your selector function, if you want to avoid unnecessary rerenders, you want to make sure the results have reference equality (===). So target the exact value you wish to look at, in your selector.
// extract the information you need from within the cart, *within the selector*
const count = useSelector(state => state.cart.items[itemId]?.count || 0)
// You don't have to use a one-liner, a multi-line function is better for readability
When Redux executes these functions, it keeps a record of the value returned from these selector functions, for each individual useSelector. This time the values are going to be the same for every single counter, except the one that actually changed. All those other counters that didn't actually change in value don't have to unnecessarily re-render anymore!
And if any of you folks think this is premature optimization, the answer's no. This is more along the lines of putting a dependancy array on your useEffects to avoid infinite loops.
Not forgetting the Level 1 optimization, we can also extract this function centrally
const selectItemById = (state, itemId) => (state.cart.items[itemId]?.count || 0);
function CartItemCounter({ itemId }){
//...
// somewhere inside a react component
const count = useSelector((state) => selectCart(state, itemId))
//...
}
So that solves all of our problems right?
For now, yes. But what if this selector function has to run some expensive computation.
const selectSomething = (state) => reallyExpensiveFn(state.cart)
//...
// somewhere inside a react component
const cart = useSelector(selectSomething)
You don't want to keep running that do you?
Or what if you have no option but to return new objects from your select function. A common scenario for this case would be returning a subset of data from the state.
const selectFilteredItems = (state) => state.itemsArray.filter(checkCondition) // the filter method will always return a new array
//...
// somewhere inside a react component
const cart = useSelector(selectFilteredItems) // re-renders every time
To solve this you would have to memoize or cache the results from the function call. Essentially you would need to make sure that if the input arguments are the same, the result will maintain reference equality with the previous result. This introduces the need to maintain some kind of cache state.
Level 3: createSelector
Fortunately, Reselect library, which is reexported with Redux Tookit, does this work for you. You can take a look at the redux toolkit for the syntax.
const selectFilteredItems = createSelector(
(state) => state.itemsArray, // the first argument accesses relevant data from global state
(itemsArray) => itemsArray.filter(checkCondition) // the second parameter conducts the transformation
)
//...
// somewhere inside a react component
const cart = useSelector(selectFilteredItems) // re-renders only when needed
Here the second function is called the transformation function, and is where we put the expensive computation, or the function that returns inconsistent references as a result (filter,map etc).
The createSelector caches
a) the arguments to the transformation function
b) the result of the transformation function
of the previous call to the selectFilteredItems function. If the arguments are the same, it skips executing the transformation function, and gives you the result you got the last time it was executed.
So when useSelector looks at the result, it gets reference equality. Hence the re-render is skipped!
One little caveat here is that createSelector only caches the very previous result. This makes sense if you think about a single component. In a single component you are only concerned about differences in values and results compared to the previous render. But in practice, you are likely to share selectors across multiple components. If this happens, you have a single cache location, and multiple components using this cache. i.e. Stuff breaks.
Level 4: createSelector factory function
Since the logic for your selector is the same, what you need to do is run createSelector for each component that uses it. This creates a cache for each component, giving us the desired behaviour. In order to do this, we use a factory function.
const makeSelectFilteredItems = () => createSelector(
(state) => state.itemsArray, // the first argument accesses relevant data from global state
(itemsArray) => itemsArray.filter(checkCondition) // the second parameter conducts the transformation
)
//...
// somewhere inside a react component
const selectFilteredItems = useMemo(makeSelectFilteredItems,[]); // make a new selector for each component, when it mounts
const cart = useSelector(selectFilteredItems) // re-renders only when needed
You intend to make a new selector (and by extension, cache) for each new component that mounts. So you put it inside the actual component function and not on the module scope. But this will re-run makeFilteredSelector for each render, and hence create a new selector for each render, and hence eliminate the cache. This is why you need to wrap the function in a useMemo with an empty dependency array. It runs on every mount.
And voila!
You now know where, why and how to use selectors in Redux. I personally feel that the createSelector syntaxes are slightly contrived. There is some discussion on changing cache sizes going on. But for now I feel that sticking to the docs should get you through most situations.
But I'm seeing all this information saying you should define your selectors beside your slice, use createSelector and all.
That's the way to go if you're deriving something from the state, which ends up being an expensive computation or something that's reused often throughout your app. Imagine, for example, your state.cart can contain 50.000 items and you need to sort them from most expensive item to least expensive. You don't want to re-calculate this all the time because it slows your app down. So you cache/memoize the result.
What is the right way, and why is it better?
The right way is to use memoization helpers like createSelector when/if you want to avoid expensive computation. Most people optimize prematurely, so I'd just stick to useSelector and keep it simple if in doubt.
I've just started using Recoil on a new project and I'm not sure if there is a better way to accomplish this.
My app is an interface to basically edit a JSON file containing an array of objects. It reads the file in, groups the objects based on a specific property into tabs, and then a user can navigate the tabs, see the few hundred values per tab, make changes and then save the changes.
I'm using recoil because it allows me to access the state of each input from anywhere in my app, which makes saving much easier - in theory...
In order to generate State for each object in the JSON file, I've created an component that returns null and I map over the initial array, create the component, which creates Recoil state using an AtomFamily, and then also saves the ID to another piece of Recoil state so I can keep a list of everything.
Question 1 Is these a better way to do this? The null component doesn't feel right, but storing the whole array in a single piece of state causes a re-render of everything on every keypress.
To Save the data, I have a button which calls a function. That function just needs to get the ID's, loop through them, get the state of each one, and push them into an Array. I've done this with a Selector too, but the issue is that I can't call getRecoilValue from a function because of the Rules of Hooks - but if I make the value available to the parent component, it again slows everything right down.
Question 2 I'm pretty sure I'm missing the right way to think about storing state and using hooks, but I haven't found any samples for this particular use case - needing to generate the state up front, and then accessing it all again on Save. Any guidance?
Question 1
Get accustomed to null-rendering components, you almost can't avoid them with Recoil and, more in general, this hooks-first React world ๐
About the useRecoilValue inside a function: you're right, you should leverage useRecoilCallback for that kind of task. With useRecoilCallback you have a central point where you can get and set whatever you want at once. Take a look at this working CodeSandbox where I tried to replicate (the most minimal way) your use-case. The SaveData component (a dedicated component is not necessary, you could just expose the Recoil callback without creating an ad-hoc component) is the following
const SaveData = () => {
const saveData = useRecoilCallback(({ snapshot }) => async () => {
const ids = await snapshot.getPromise(carIds);
for (const carId of ids) {
const car = await snapshot.getPromise(cars(carId));
const carIndex = db.findIndex(({ id }) => id === carId);
db[carIndex] = car;
}
console.log("Data saved, new `db` is");
console.log(JSON.stringify(db, null, 2));
});
return <button onClick={saveData}>Save data</button>;
};
as you can see:
it retrieves all the ids through const ids = await snapshot.getPromise(carIds);
it uses the ids to retrieve all the cars from the atom family const car = await snapshot.getPromise(cars(carId));
All of that in a central point, without hooks and without subscribing the component to atoms updates.
Question 2
There are a few approaches for your use case:
creating empty atoms when the app starts, updating them, and saving them in the end. It's what my CodeSandbox does
doing the same but initializing the atoms through RecoilRoot' initialState prop
being updated by Recoil about every atom change. This is possible with useRecoilTransactionObserver but please, note that it's currently marked as unstable. A new way to do the same will be available soon (I guess) but at the moment it's the only solution
The latter is the "smarter" approach but it really depends on your use case, it's up to you to think if you really want to update the JSON at every atom' update ๐
I hope it helps, let me know if I missed something ๐
Following the example on the reselect docs:
import { createSelector } from 'reselect'
const shopItemsSelector = state => state.shop.items
const subtotalSelector = createSelector(
shopItemsSelector,
items => items.reduce((acc, item) => acc + item.value, 0)
)
In a typical redux app, subtotalSelector will recompute if a user updates item.name, even though this has no impact on the result. Is there a way to avoid this?
Two solutions:
Let it be. Unless you have a large number of items, the browser's computing capacity is well enough to handle the recompute.
Seperate prices from the item object. That is, you have state.shop.items.itemNames(containing id-name pairs) and state.shop.items.itemValues(containing id-value pairs). Then only the itemValues is passed to the selector.
I have a similar problem and I have found a sort of hack to get arround it.
I have a complex set of filters, and a huge number of items to filter through. Part of the filter state includes display state. I want to ignore changes in the display state so I don't filter a huge list all the time. This is an easy-ish solution:
const getFilters = createSelector(
state => state.filters,
filters => {
const filtersWithoutDisplay = {};
const ignoreObj = { collapsed: null };
for (let filterGroup in filters) {
filtersWithoutDisplay[filterGroup] = Object.assign({}, filters[filterGroup], ignoreObj);
}
// We create a new object every time, so this cannot be memoized properly unless we stringify.
return JSON.stringify(filtersWithoutDisplay);
}
);
It returns a JSON string that has to be parsed, but it's a primitive so as an input to another selector it doesn't trigger a recomputation if the actual contents don't change. That's kind of a hack.
You could also define an object outside of the selector function and always keep the same reference, change the insides according to this same patter, and then use a custom deep equality check by pulling in createSelectorCreator, as explained here https://github.com/reactjs/reselect#q-why-is-my-selector-recomputing-when-the-input-state-stays-the-same . This is probably a better way to go, but as it says:
Always check that the cost of an alternative equalityCheck function or deep equality check in the state update function is not greater than the cost of recomputing every time.
That goes for the JSON.stringify hack as well. I wouldn't do it for the huge list, but for the filters, sure.
In my situation, it's probably better to refactor my state because the filter values may be a separate concern from the filter display settings, and this may not be the only time I want them separate.
I am in the early development stage of a React+Redux game and have followed Redux best practices: pure reducer, presentational/container component separation, using getState() only in Reducer (as opposed to in action creator) etc. The app seems to be working as expected but when I try to reverse an action using Time Travel, even though the state property map[][] and it's computed connected component prop change as expected, the result doesn't get reflected on the UI properly (specifically the player position on the map doesn't follow what state dictates). When I inspect the state changes I can see that all necessary changes are correctly taking place between different states. Here is my reducer:
const gridReducer = (state, action) => {
if (typeof state === 'undefined'){
let dungeon = new Dungeon();
dungeon.generate();
return {
boardWidth: Math.floor(((70/100) * window.innerWidth) / 20),
boardHeight: Math.floor(((70/100) * window.innerHeight) / 20),
map: dungeon.map,
position: dungeon.playerPosition
}
}
switch (action.type) {
case 'GRID_RESIZE':
return {...state,
boardWidth: action.newBoardWidth,
boardHeight: action.newBoardHeight
}
//This is where I have the issue, map correctly changes both when interacting with the game and when reversing using time travel however the UI fails to update (only in reverse)!
case 'MOVE':
let dungeonObj = new Dungeon(state.map.slice(), {...state.position});
if (dungeonObj.movePlayer(action.direction)) {
return {...state,
position: dungeonObj.playerPosition,
map: dungeonObj.map
}
} else return state;
default:
return state;
}
}
Here is the complete code if you want to take a look! The app currently only supports moving the player in the dungeon by pressing arrow keys and the view is supposed to always be centeral based on the position of the player (player fails to move back when using time travel)
http://s.codepen.io/sabahang/debug/GjrPNQ
PS: Dungeon.generate does use Math.Random but I'm only using this function in initialState and for dispatched actions I'm only making a shallow copy of the generated map by sending the current state to Dungeon constructor and use its other methods (eg. movePlayer)
Found the culprit. It's not Redux's fault at all, it's about the way React works! If you are new to React and you haven't fallen into this trap yet wait for it!
It has to do with the fact that most of the conventional ways of copying a deeply nested object which is needed in Redux to implement a pure Reducer is in fact making a shallow copy of the objects and properties' memory references are still pointing to the original State. React updates the UI based on a deep comparison of the old state and the new one and when some of the references are the same it fails to update the UI properly. Here I have a 2 dimensional array map[][] which is an object and although I'm using ES6 spread operator to avoid modifying the original state because a shadow copy is being made, deeply nested indexes of the original map[][] are being modified. One solution would be to use `Array.map()' to create a completely new object but I ended up using immutablejs and it fixed my problem with the time travel slider.
This is a highly recommended reference if you don't want to spend weeks chasing similar bugs in complicated apps: http://redux.js.org/docs/recipes/reducers/ImmutableUpdatePatterns.html
and there are tons of immutability helpers to help based on your specific need:
https://github.com/markerikson/redux-ecosystem-links/blob/master/immutable-data.md#immutable-update-utilities
This one also looks interesting for Redux only:
https://github.com/indexiatech/redux-immutablejs
This question is potentially a duplicate of the following:
React-redux store updates but React does not
I'm building a front-end for a search system where almost all user actions need to trigger the same async action to re-fetch search results. For example, if a user enters a keyword, then we need to fetch /api/search?q=foo, and if they later select a category we fetch /api/search?q=foo&categoryId=bar. I originally had separate action types for FETCH_RESULTS, SELECT_CATEGORY, DESELECT_CATEGORY, etc. I created one asynchronous action creator for FETCH_RESULTS, but the others are synchronous. The more I think about it, they all end up needing to re-fetching the results from the backend and update the app state based on the response from the backend.
Would it make sense for me to use the single async action-creator for any change? Or would it be better to use async action creators for each distinct user action (selecting a keyword, category, or filter)?
I think the advantage of granular actions would be the events more accurately reflect what the user did (e.g. the user selected a category) vs having to peer into the payload to figure out what actually changed, but they are all pretty similar.
This is of course something only you can really answer based on what you know about the project. I don't think that there is any inherent advantage to having the actions be more granular, and if there aren't any, its not worth the extra effort. I would have a generic FILTER_CHANGED event and not worry about being able to see what specifically changed--presumably the action isn't going to be complicated, so I'm not going to be debugging the action a lot. As the filter state becomes more complicated and diverse, it might make more sense to break out the actions. By default though, I don't really see much value.
I fully agree with Nathanโs answer.
I just want to add that in order to tell whether actions A and B are really one or two actions, you need to ask yourself: โIf I change how some reducers react to A, will I also need to change how they react to B?โ
When the handlers change together in the reducer code, itโs likely they should be a single action. When their changes may not affect each other, or if many reducers handle just one of them but not the other, they should probably stay separate.
I agree with Dan Abramov: if the text and categories are highly coupled in your interface, just fire FETCH_RESULTS with the text and categories as action payload.
If the text input and categories selection widget do not share a close parent component, it is complicated to fire a FETCH_RESULTS which contains the text and categories (unless passing a lot of props down the tree...): you then need the action granularity.
One pattern that I have found helpful when such granularity is needed is the Saga / Process manager pattern. I've written a bit about it here: https://stackoverflow.com/a/33501899/82609
Basically, implementing this on redux would mean there's a very special kind of reducer that can trigger side-effects. This reducer is not pure, but do not have the purpose of triggering React renderings, but instead manage coordination of components.
Here's an example of how I would implement your usecase:
function triggerSearchWhenFilterChangesSaga(action,state,dispatch) {
var newState = searchFiltersReducer(action,state);
var filtersHaveChanged = (newState !== state);
if ( filtersHaveChanged ) {
triggerSearch(newFiltersState,dispatch)
}
return newState;
}
function searchFiltersReducer(action,state = {text: undefined,categories: []}) {
switch (action.type) {
case SEARCH_TEXT_CHANGED:
return Object.assign({}, state, {text: action.text});
break;
case CATEGORY_SELECTED:
return Object.assign({}, state, {categories: state.categories.concat(action.category) });
break;
case CATEGORY_UNSELECTED:
return Object.assign({}, state, {categories: _.without(state.categories,action.category) });
break;
}
return state;
}
Note if you use any time-traveling (record/replay/undo/redo/whatever) debugger, the saga should always be disabled when replaying actions because you don't want new actions to be dispatched during the replay.
EDIT: in Elm language (from which Redux is inspired) we can perform such effects by "reducing" the effects, and then applying them. See that signature: (state, action) -> (state, Effect)
There is also this long discussion on the subjet.
EDIT:
I did not know before but in Redux action creators can access state. So most problems a Saga is supposed to resolve can often be solved in the action creators (but it creates more unnecessary coupling to UI state):
function selectCategory(category) {
return (dispatch, getState) => {
dispatch({type: "CategorySelected",payload: category});
dispatch({type: "SearchTriggered",payload: getState().filters});
}
}