Apollo js refetchQueries does not fire requests - javascript

I am using Apollo Client without React, just plain ol JS. I have a classic table and modal that adds things to the backend. Once I add the thing using client.mutate() I'd like to update the table. If the table is not on the last page, it doesn't really matter, the user will eventually click there to get to the new row. But if the user is on the last page or has visited the last page at any point, going back to that page will not display the new row.
In React I was able to do something like
useMyMutation({
variables: {},
refetchQueries: [getOperationName(SomeDocument)]
})
And what this did was refetch the provided query name with its last used variables. I'd like to do something similar and I've been reading the docs and trying this and that but can't even get a query to trigger on the network.
client.mutate(
mutation: MyMutation,
variables: {a:1},
refetchQueries: (e: any) => "all", // nothing I put here ever does anything
)

Related

Send text from HTML search bar to backend through JS

I am using Bootstrap in HTML to create a search page, where users will type a SQL query, and then that SQL query will connect to a backend which will run the query in a database. The backend is in a separate code, and so I'm trying to take the query text and send it to the backend. I am pretty lost on this, and just need an idea of what type of function to build to do this.
The plan is to have an onclick=function and then use the function to send the text to the backend. I can't seem to find any packages or functions that do this, even though I'm sure they are out there/readily accessible. I have looked at AJAX, but can't really find anything that does exactly this.
You don't need any libraries for that
// get the search bar
const input = document.querySelector('input')
// get the button
const button = document.querySelector('button')
// set event listener
button.addEventListener('click', () => {
// run ajax request
fetch('http://yoururlhere?query=' + input.value)
})
<input>
<button>Search</button>

How to have a 'placeholder' or Home Screen without API call on page landing?

I would like wisdom again.
I am making a single page application with quite a bit of AXIOS calls, as you can see here.
useEffect(() => {
axios.all([
axios.request(options),
axios.request(optionsQuote),
axios.request(optionsDaily),
axios.request(optionsNews)
],)
.then(response => {
setData(response)
})
console.log(data);
}, [tix])
My conundrum is that this runs every time I land on the page (for obvious reasons) and have to have an initial data in order for the app to run.
const [tix, setTix] = useState('AAPL')
I want to be able to land on a 'placeholder' type data, so to avoid the first initial call and only call when user searches and clicks on the company name, data. This function works fine after the page lands and initial stock (AAPL) is called. I want to not call it.
The problem is, I am trying to make a single page web app and would like to avoid using routes, if possible.
If I leave the initial state as blank (''), than, the code breaks since all of my data is derived from the fact that "data" has data in it.
const [data, setData] = useState(null)
Is the only way for me to get initial page without data showing is to make another component (such as 'landingPage')? If so, how do I go about doing that?

Parse JavaScript SDK subscription using containedIn

I'm trying to retrieved chats that a particular user is part of and that works but when I'm subscribing to that query and someone starts a chat me or I start a chat with a new person, it doesn't update. When I manually reload the page, it gets the latest chats so I think my query works but subscribing to it doesn't.
Here's my query:
let query = new Parse.Query("Chat");
query = query.containedIn("members", [Parse.User.current()]);
And here is the subscription:
let subscription = query.subscribe();
subscription.on("create", chat => addChatToView(chat))
I tried to do it manually by omitting the second line and subscribe to whole table and using lodash to somehow filter the results.
Is there any solution to this aside from doing it manually?

Redux - Remove object from store on http response error

Consider the following flow:
I have a page with a list of "products" and a modal to create a single "product". I open the modal, fill the form and submit the form.
At this point, I dispatch an action CREATING_PRODUCT, add the product to the store and send the http request to the server.
I close the modal and display the list of results with the new product.
Let's suppose I receive an error response from the server.
Desired behavior:
I would like to display an error, remove the project from the list, re-open the modal and display the form already filled.
Question
How can I find that project and remove it the list? I don't have an id (or a combination of unique properties) to find that project in the store. I don't see a clean way to link a request/response to that "product" object in the store.
Possible solution
The client adds a "requestId" into the project before adding it to the store. On response error, I dispatch a generic "CREATE_ERROR" and I remove the project with that requestId from the store.
Extra
Same problem with edit and delete. For example during a delete should I keep a reference to the deleted project with the requestId in the store, until the http request is successful?
I bet it is a problem with a common solution, but I can't find examples.
Thanks!
In general, your Redux store should be modeled somewhat like a relational database, in that every time you have a list of data models, each element of the list should have its own identifier. This helps a lot when dealing with more complex data schemes.
You should probably store your projects as an object, something like:
{
// ...other store properties
projects: {
"_0": { // ... project properties }
"_1": { // ... project properties }
// ...more projects...
},
}
This way, whenever you need to mess with an existing project, you can just reference its id and use projects[id] to access that project. This would also solve the edit and delete cases, as you could just pass the IDs around as handles.
I like this short piece on why your Redux store should be mostly flat and why data should always have identifiers very much. It also talks about using selectors to "hide" your IDs away, which may or may not be useful for you.
In your case, as you are getting IDs from a server, you could have an ID prefix which indicates unsaved values. So your projects object would become something like:
projects: {
"_0": { // ... }
"_1": { // ... }
"UNSAVED_2": { // ... }
}
This way, you could easily identify unsaved values and handle them when an error occurs, still get the benefits of generating temp IDs on the client-side in order to revert changes on error, and also warn your user if they try to leave your app while their data still hasn't been synchronized - just check if there are any "UNSAVED" IDs :)
When you get a response from the server, you could change the "UNSAVED_suffix" ID to an actual ID.

How to choose the Redux state shape for an app with list/detail views and pagination?

Imagine I have a number of entries(say, users) in my database. I also have two routes, one for list, other for detail(where you can edit the entry). Now I'm struggling with how to approach the data structure.
I'm thinking of two approaches and a kinda combination of both.
Shared data set
I navigate to /list, all of my users are downloaded from api a stored in redux store, under the key users, I also add some sort of users_offset and users_limit to render only part of the of the list
I then navigate to /detail/<id>, and store currently_selected_user with <id> as the val... which means I will be able to get my user's data with something like this users.find(res => res.id === currently_selected_user)
updating will be nice and easy as well, since I'm working with just one data set and detail pointing to it
adding a new user also easy, again just working with the same list of users
Now the problem I have with this approach is that, when the list of users gets huge(say millions), it might take a while to download. And also, when I navigate directly to /detail/<id>, I won't yet have all of my users downloaded, so to get data for just the one I need, I'm gonna have to first download the whole thing. Millions of users just to edit one.
Separated data set
I navigate to /list, and instead of downloading all of my users from api, I only download a couple of them, depending on what my users_per_page and users_current_page would be set to, and I'd probably store the data as users_currently_visible
I then navigate to /detail/<id>, store currently_selected_user with <id> as the val...and instead of searching through users_currently_visible I simply download user's data from api..
on update, I'm not gonna update users_currently_visible in any way
nor will I on add
What I see as possible problem here is that I'm gonna have to, upon visiting /list, download data from api again, because it might not be in sync with what's in the database, I also might be unnecessarily downloading users data in detail, because they might be incidentally already inside my users_currently_visible
some sort of frankenstein-y shenanigans
I detail, I do the same as in Separated data set but instead of directly downloading user's data from api, I first check:
do I have any users_currently_visible
if so, is there a user with my id between them?
if both are true, I then use it as my user data, otherwise I make the api call
same happens on update, I check if my user exists between users_currently_visible if so, I also update that list, if not I do nothing
This would probably work, but doesn't really feel like it's the proper way. I would also probably still need to download fresh list of users_currently_visible upon visiting /list, because I might have added a new one..
Is there any fan favorite way of doing this?... I'm sure every single one redux user must have encountered the same things.
Thanks!
Please consult “real world” example from Redux repo.
It shows the solution to exactly this problem.
Your state shape should look like this:
{
entities: {
users: {
1: { id: 1, name: 'Dan' },
42: { id: 42, name: 'Mary' }
}
},
visibleUsers: {
ids: [1, 42],
isFetching: false,
offset: 0
}
}
Note I’m storing entities (ID -> Object maps) and visibleUsers (description of currently visible users with pagination state and IDs) separately.
This seems similar to your “Shared data set” approach. However I don’t think the drawbacks you list are real problems inherent to this approach. Let’s take a look at them.
Now the problem I have with this approach is that when then list of users gets huge(say millions), it might take a while to download
You don’t need to download all of them! Merging all downloaded entities to entities doesn’t mean you should query all of them. The entities should contain all entities that have been downloaded so far—not all entities in the world. Instead, you’d only download those you’re currently showing according to the pagination information.
when I navigate directly to /detail/, I wouldn't yet have all of my users downloaded, so to get data for just the one, I'm gonna have to download them all. Millions of users just to edit one.
No, you’d request just one of them. The response action would fire, and reducer responsible for entities would merge this single entity into the existing state. Just because state.entities.users may contain more than one user doesn’t mean you need to download all of them. Think of entities as of a cache that doesn’t have to be filled.
Finally, I will direct you again to the “real world” example from Redux repo. It shows exactly how to write a reducer for pagination information and entity cache, and how to normalize JSON in your API responses with normalizr so that it’s easy for reducers to extract information from server actions in a uniform way.
I also used normalizr approach before to normalize entities, but the problem with it is that this requires manual work.
If you know Apollo in GraphQL world, you probably know that it supports automatic normalisation, so data for a given object is not stored in multiple places. Thx to that they also support automatic updates, if your server responds with an object with the same id but with updated attrs, Apollo will recognize it and update this object in multiple places.
However, why this luxury should be reserved only for GraphQL? Due to this reason I implemented redux-requests library, which supports automatic normalisation for any API, REST, GraphQL, Firebase, whatever. How does it work? Imagine you have a book list and detailed endpoints. To communicate with them, you would just dispatch Redux actions like that:
const fetchBooks = () => ({
type: FETCH_BOOKS,
request: { url: '/books' },
meta: { normalize: true },
});
const fetchBook = id => ({
type: FETCH_BOOK,
request: { url: `/books/${id}` },
meta: { normalize: true },
})
Now, to update title of a book in both places, we would just do:
const updateBookTitle = (id, newTitle) => ({
type: UPDATE_BOOK_TITLE,
request: { url: `books/${id}`, method: 'PATCH', data: { newTitle } },
meta: { normalize: true },
})
If you are interested with such an approach, more about it could be read here

Categories

Resources