Add the ability to mutate pageProps #78
Replies: 14 comments 9 replies
-
So, in your example, why wouldn't you just do an |
Beta Was this translation helpful? Give feedback.
-
This probably doesn't matter in the posts example, however, if you're dealing with data that changes often, there's a chance that your list has completely changed by the time you do the If you're on page 2 of a list, modify an item, and receive a new set of data for page 2, there's a chance that the item you modified isn't part of the list anymore, which would be super confusing for the user. We do this in Flare, since errors can come in pretty fast is an application is on fire. We use Axios call to resolving or snoozing errors to ensure the context doesn't completely change after a request. |
Beta Was this translation helpful? Give feedback.
-
Ahh yes, real interesting. That makes sense. Something that needs to be considered here is that if we change the props somehow, we'll also need update the cached history state data as well. I also wonder, with a feature like this, if you'll quickly get into modifying the URLs and history state as well. I feel like this is a dangerous road to go down, but will be very tempting. |
Beta Was this translation helpful? Give feedback.
-
So, I'm seeing some interesting use cases for a feature like this, where you can modify the root level props (page object), which then reactively updates the page component props. One really neat use case for this is infinite scrolling. Imagine you have a tweets page, that shows the 15 most recent tweets. Then, when you scroll and load additional tweets, you could use something like loadMoreTweets() {
fetch(`/tweets?page=${nextPage}`)
.then(response => response.json())
.then(tweets => Inertia.updateProps(props => {
props.tweets.concat(tweets)
return props
}))
} A different approach would be to allow per visit prop transformations: loadMoreTweets() {
let currentTweets = this.tweets
Inertia.get(`/tweets?page=${nextPage}`, {
transformProps(props => {
props.tweets = currentTweets.concat(props.tweets)
return props
})
})
} I like this approach as well, for two reasons. One, you can still make these requests with Inertia, and second, transforming props is already a thing in Inertia. However, I suspect the |
Beta Was this translation helpful? Give feedback.
-
In React-land there's a library called SWR that helps you deal with fetching/caching/invalidating data. SWR has a very interesting
// update the local data immediately, but disable the revalidation
mutate('/api/user', { ...data, name: newName }, false)
// send a request to the API to update the source
await requestUpdateUsername(newName)
// trigger a revalidation (refetch) to make sure our local data is correct
mutate('/api/user') I think there are some interesting ideas in there we could use as inspiration, including the name. function updateUser(user) {
Inertia.mutate(props => ({ ...props, user }));
Inertia.post('/users/123', { user });
} |
Beta Was this translation helpful? Give feedback.
-
Sorry for opening up this old thread, but I have a use case where mutation of props would be great to have. |
Beta Was this translation helpful? Give feedback.
-
I am facing this use case quite often.Right now I am cloning prop into data which can be mutated. |
Beta Was this translation helpful? Give feedback.
-
I have a situation where manually updating the page props would be ideal (I stupidly assumed it would be possible) I'm using Laravel Echo to subscribe to a channel which broadcasts an event that returns the data I need to update the prop with. I could do an Inertia.reload() but that's not great for user experience and seems like overkill considering the event has already returned the data. The prop itself is shared across all routes (via middleware) and is referenced in multiple places (I've put the channel registration in the shared layout). Any thoughts would be welcome |
Beta Was this translation helpful? Give feedback.
-
Someone find a way to update the prop with a Laravel Echo data in VueJS? |
Beta Was this translation helpful? Give feedback.
-
I am also facing this issue and have solved it with a Pinia-store. The problem which occurred though is that I want the history state functionality that comes with Inertia. Even though I’m modifying my store or have a local variable in my component which I can mutate they will be overwritten if I watch the Inertia page-object for changes. So I solved this by digging into the Inertia source code and actually modify the history state with the updated props. The problem that I got there was that Inertia replaces the state with it’s local page object when navigating to a new page to save the scroll position inside the state. So I figured the only way to alter the page object inside the Inertia class was to use the popstate listener which gets the page object from the state. Here’s what I came up with: import { usePage } from '@inertiajs/inertia-vue3';
import { defineStore } from 'pinia';
import { ref, watch } from 'vue';
export const useStore = defineStore('props', () => {
const pageProps = usePage().props;
const props = ref(structuredClone(pageProps.value));
let inertiaRefresh = false;
let propsRefresh = false;
watch(
() => pageProps.value,
(newProps) => {
if (inertiaRefresh) {
inertiaRefresh = false;
return;
}
propsRefresh = true;
props.value = {
...props.value,
...newProps
};
}
);
watch(
() => props.value,
() => {
if (propsRefresh) {
propsRefresh = false;
return;
}
// Get current state
const currentState = structuredClone(window.history.state);
const stateData = {
...currentState,
props: structuredClone(props.value)
};
// Update state
window.history.replaceState(
stateData,
'',
currentState.url
);
// Push the same state to the history stack
window.history.pushState(
stateData,
'',
currentState.url
);
// Refresh Inertia, this will trigger an update to the page props
inertiaRefresh = true;
window.history.back();
},
{
deep: true
}
);
return {
props
};
}); It’s a dirty solution but it works😄 it’s handy when I need to do requests without the Inertia methods or update props using Laravel Echo. Would be lovely if this could be done in a more official way with methods inside Inertia. The PR that @vinnygambiny created gets a +1 from me! Update: This worked for updating the page props but caused some issues with the scrollposition being changed. So I’m doing a fork of Inertia which is able to mutate the page props. |
Beta Was this translation helpful? Give feedback.
-
Hi, Any Update on this? I have a situation where i need to push the url state without the need to make any server side visit |
Beta Was this translation helpful? Give feedback.
-
I'm not sure if this is the best idea (please correct me if it is bad), but in Vue I noticed I could do something like the following snippet. It was to solve the issue of import { usePage } from '@inertiajs/vue3';
import axios from 'axios';
const $page = usePage();
const foos = ref($page.props.foos);
function saveFunction(item) {
axios
.put(route('foo.route'), {
id: item.id,
})
.then((response) => {
$page.props.foos = response.data.foos;
});
} I do like it better than using |
Beta Was this translation helpful? Give feedback.
-
I've been building apps with Inertia for a few years now and I keep hitting the issue where I need to update page props with data passed through a Laravel broadcast event. Normally I use the lazy reload functionality and make a router.reload request. Although it works, it doesn't feel right. The data I need is already provided in the broadcast event but because there isn't a clean way to update the page props I have to reload the whole data set. I understand the reason we don't normally mutate props but the alternative of reloading seems less than ideal. It would help me a lot if there was a way to do this. |
Beta Was this translation helpful? Give feedback.
-
I actually created a fork of inertia where I have solved this issue for anyone interested: This allows you to modify the page props without reloading. Here are the NPM repos: |
Beta Was this translation helpful? Give feedback.
-
Sometimes I wish there was a way to mutate the page props.
For example: you have a list of posts that have a publish button that uses Axios. After clicking publish, the post's status needs to be updated.
The current way of doing thigs:
posts
object in the responseposts
object to local component state, which may be mutatedInertia.visit
happens withpreserveState
, you need to manually override your local component state with the freshposts
dataThis is really annoying to maintain, and would be simpler if we could just mutate the prop in Inertia.
This is a potentially dangerous feature, so I'm not sure about it yet. Would like some external input.
Beta Was this translation helpful? Give feedback.
All reactions