Update the cache and trigger a re-render in Apollo - javascript

I'm trying to update the cache of a certain item but changes aren't being reflected on to the ui , I have an item which is being fetched by a query that has a lot of variables and I have no access to them on the component that I'm updating that Item on and that Item is also part of a paginated list , so my code was
update = (cache)=>{
cache.data.data['ItemType_'+itemId].title = "New title"
}
as far as I know this code should update the cache of that item but it doesn't show it in the ui , is there a way to update a single item in the cache and have the result rendered ?

Directly updating the cache doesn't cause a re-render afaik. I recommend running a query with fetchPolicy: "cache-only" after you update the cache. That will update the component's data and cause a re-render without hitting the network.

Try and also make sure you are returning the correct data from the mutation.
Return the correct fields from the mutation. The required field can be id. If it is not returned from the mutation, then there will be no refresh or re-render.

Related

Updating the useState values automatically in react js?

I have a usestate array object called mo, which gets the data from an rest api from get request. I use useEffect for getting the data.
const [mo, UpdateMO] = useState([{}]);
I will be creating an item by post request and that newly created item is stored in tempArray. This newly created item is appended to the mo array object.
UpdateMO([...mo], tempArray);
I show all the values of mo in a table. It is getting updated only once a re-render or refresh is taking place. On refreshing I would be going back to the homepage. So, how can I refresh or re-render the mo so that on creating a new item it automatically re-renders the mo.
Setting state will be done asynchronously. When you want to update state, you can grab the previous values in the state to combine with the new values.
Setting state also triggers a re-render.
// initialize state with an empty array
const [mo, setMo] = useState([]);
// get newValues and update state
setMo((previousValues) => [...previousValues, newValues]);
Use redux for that to maintain data and update data

React: Mapping a component with local storage data

I'm currently creating a history list component for a form in a react app and am having some trouble with the local storage.
Essentially, I want the app to render a list of past inputs from the user's local storage data. My current idea is based in duplicating the local storage data is a state variable.
const [history, setHistory] = useState([]);
On form submit I call this function with the form input as the parameter (the input is a single string)
const setLocalStorage = (input) => {
const hist = JSON.parse(localStorage.getItem('history')) || [];
console.log(hist)
hist.push(input)
localStorage.setItem('history', JSON.stringify(hist))
setHistory(hist);
}
This is meant to put the history from local story into hist, push the input that was just submitted into the existing array hist, and update the local storage with the new value. The state variable should then be updated with the most updated array of strings with the setHistory(hist) call.
Also, I want local storage to be pulled on first render so I can use that data to render the history list on initial load. I have a useEffect hook for this as shown:
useEffect(() => {
setHistory(JSON.parse(localStorage.getItem('history')))
console.log(history)
}, []);
The problem I'm facing is that the state never seems to get updated? I can instead do a console log for JSON.parse(localStorage.getItem('history')) and get the local storage array returned but this of course isn't helpful for data usage. I know that the local storage is properly being pulled from this but I'm unable to update the state for some reason. I need the state updated so I can conditionally render and use the array for mapping each item on the history list. When I console log "history" I get an empty array.
TL;DR
Concisely, what is the cleanest method to have local storage and state values maintain equivalency? Hope my post was clear enough to understand!
I'm remaking and updating a regular JS app on React for practice so I'm able to provide a live link of how I want this simple component to work.
https://giovannimalcolm.github.io/weather-dashboard/
The second returned parameter of useState is similar to the this.setState which is asynchronous. You may see that state is not changed even setHistory is called. Passing function instead of the value will avoid this issue as it will be executed after the state is updated. This might be useful for better understanding Passing function to setState()
useEffect(() => {
const hist = JSON.parse(localStorage.getItem('history'))
setHistory(prevHistory => [...prevHistory, ...hist])
}, []);

Sharing a State Array

Have kinda a unique question, in my code I have a listener to a database that loads down objects into an array.
All I do when I load it in is
AddObject(obj){
this.setState({
Data: [...this.state.Data, obj]
});
}
Pretty simple. However this listener function, there is no exact time when need data will be added. When I go to use that Data sent in Data, I went to pull it out of the Data Array, however I am worried if I try copying data out of the array, or removing the "seen" data, I will get weird behaivor if my listener function triggers and I try adding data to the array at the same time.
Is there some sort of a way to do this? I guess you could call this a shared resource
Ideally, I would have something like this:
loadDataIN(){
var LengthToGrab = this.state.Data.length;
//we need to remove this length, now any new data will be added to index 0
}
Does this make sense? basically I am trying to figure out the best way to remove data from this array, and not have to worry about overwritting, or losing data. Maybe some sort of processing que
From official doc
setState() enqueues changes to the component state and tells React
that this component and its children need to be re-rendered with the
updated state.
You don't need to worry that two kinds of situation would have conflict in the same time.
setState() enqueues the pending state before the changes be rendered.
In fact, no matter how mechanism be implemented, React is a framework of JavaScript which is working on a model event-loop.
So if you want to pull out the data from this.state.Data:
loadDataIN(){
this.setState(function(prevState, props) {
// this.fetchData = prevState.Data;
return {
Data: []
};
});
}

React object.map not updating due to the key

The basic problem I'm having is that I'm updating my data using an AJAX request and then setting the state of data, but in the view, the data never update even though my state is updated. I've figured out that it's because the key is the same (which it should be because I'm just using the ID mongoose provides).
If I do things like set the state to nothing and then set then set the new data then it updates. Or if I set the key to a randomly generated key it also works, but both of these don't feel right. I want to know what the correct way to re-render an updated object when using the map function.
It looks something like this:
Object.keys(this.state.data).map((i) => (
<MyComponent key={ this.state.data[i]._id }
))
And then I have a basic AJAX request that does this.setState({ data: response.data }).
How do I make react update the data in the view for the updated item properly?
Can you add the index as a prefix to the _id?
key={ `${i}_${this.state.data[i]._id}`}
I am not really sure it is related to the key, if you console.log(this.state.data) just before your code it gets updated when it should? it seems to me that the props are not getting passed to the component.
I mean I often use the index of map in the key in the lists I never had any problem with that.

Dynamic defaultValue on Combobox React Widgets

I'm fairly new to javascript and I'm currently making a web client that display some data a database. Pretty standard stuff I guess. I use react.js and I installed react-widgets to get some nice widgets. The comboxbox I use is getting it's data from a mongo database depending on the collection chosen from another comboxbox. So by changing the collection, the data inside is updated to reflect the change. This works well, but I can't seem to be able to set the default value. Here the code to render the comboxbox:
<Combobox onChange= {this.handleOnChange} data = {this.state.myValues} defaultValue= {this.state.myValues[0]}/>
I have had this issue with a couple of widgets that does not seem to be able to get updated dynamically. They work if all the data is there the first time I'm rendering (static data for example), but they don't if the data is empty at first and gets populated afterward. *I did make sure I call setState to call the render function.
Did I miss something? Is it a javascript issue that I don't understand?
Thanks!
Try wrapping the Combobox with a condition.
Something like this
{ this.state.myValues[0] &&
YOUR_TAG_COMBO
<Combobox onChange= {this.handleOnChange} data = {this.state.myValues} defaultValue= {this.state.myValues[0]}/>
}
I think you might be better off using the value prop, instead of defaultValue, it will give you more control over the component, and it will repopulate the form element when the state has changed.

Categories